Wordlist Generator All articles
Linguistics / 4 min read

The Schwa Doesn’t Care About Your Spellcheck

Marcus Oyelaran Nov 10, 2026
The Schwa Doesn’t Care About Your Spellcheck

Most wordlists are built by people who trust spelling. Users do not. Users type what they hear in their own head, and American English is full of pronunciation shortcuts that never make it into a spellchecker. The result is a quiet gap in your candidate list: passwords that look wrong on paper but sound right to the person typing them.\n\nThe schwa is the star of this problem. It is the unstressed vowel sound in the middle of banana, the fuzzy vowel in separate, and the reason definitely becomes definately in a hurry. Spellcheck flags the result. A wordlist should not.\n\n## Why pronunciation-aware wordlists matter\n\nIf your list contains separate but not seperate, you are assuming a level of spelling discipline that people do not have under pressure. If it contains write but not rite, you are assuming homophones are rare. They are not. English is full of them, and passwords inherit the confusion.\n\nThe CMU Pronouncing Dictionary, usually called CMUdict, is a practical fix. It maps English words to ARPAbet phonemes, including stress markers. That lets you group words by sound instead of spelling. It is not perfect for slang, brand names, or the latest event vocabulary, but it is a strong starting point for common words.\n\n## Homophones are free candidates\n\nThe simplest CMUdict trick is to strip stress digits and group words by their remaining pronunciation. Words that land in the same bucket are homophones, or close enough to generate useful variants. Right and write belong together. So do there, their, and they’re in many accents, along with to, too, and two.\n\nHere is a code-golf-ish way to harvest those groups:\n\npython\nimport collections as C\nd=C.defaultdict(list)\nfor l in open('cmudict.dict'):\n w,p=l.split(' ',1)\n d[''.join(c for c in p if not c.isdigit())].append(w.strip())\nprint(chr(10).join(' '.join(v) for v in d.values() if len(v)>1))\n\n\nThat snippet is deliberately small. It does not normalize case, handle punctuation, or filter rare words. Those are choices you should make on purpose. The point is to see pronunciation groups before you start layering rules on top of spelling.\n\n## Flapping, dropping, and merging\n\nAmerican English does more than swap homophones. In many accents, a t between vowels becomes a flap that sounds like d. Butter becomes budder. Little becomes liddle. Water becomes wadder in plenty of dialects. A wordlist that includes water but not wadder is missing a real typing pattern.\n\nThen there is syllable dropping. Probably becomes probly. Family becomes famly. February becomes Febuary. Vowel mergers matter too: the cot-caught merger can make caught and cot sound identical, and the pin-pen merger can flip pen and pin for millions of speakers.\n\nA small rule set is better than a giant one. You want dialect-aware variants, not a combinatoric explosion of every possible vowel. Try something like this:\n\npython\nW='butter little water running probably family'.split()\nR=[('tt','dd'),('tle','ddle'),('t','d'),('ing','in'),('ably','bly')]\nprint(chr(10).join({x.replace(a,b) for x in W for a,b in R}|set(W)))\n\n\nThat is not linguistically exhaustive. It is a starting point for flap rules and dropped syllables. Apply it to roots that already matter in your list, not to every word in the dictionary.\n\n## The schwa deserves its own pass\n\nThe schwa is tricky because it is not one spelling. It is a sound that can be written as a, e, i, o, or u depending on the word and the typist. Separate can become seperate. Definitely can become definately. Banana can become bananna.\n\nA focused schwa pass can generate vowel substitutions in unstressed positions, but you need a budget. If you swap every vowel in every word, you get noise. If you target common misspelling patterns and high-value roots, you get signal.\n\n## Tag the rule, not just the word\n\nOne useful habit is to label each variant with the rule that produced it: flap, schwa, merger, dropped-syllable. That turns your wordlist from a pile of strings into an auditable model. When a candidate hits, you can ask why. When a rule produces too much junk, you can turn it down.\n\nThis is also a fairness issue. Not every American speaks the same dialect. A pronunciation-aware list should not pretend there is one correct accent. It should document which patterns it models and let the operator decide what belongs.\n\n## Keep the scope authorized\n\nPronunciation variants are for authorized security testing, puzzle generation, and linguistic experiments. They are not a license to guess at real accounts. The technique is neutral; the use is not. Keep your lists documented and your testing scoped.\n\nThe schwa does not care about your spellcheck. If your wordlist only cares about spelling, it is missing people who type exactly the way they talk.

All Articles

Keep Reading

Next transmissions
Data Provenance 10.11.26
A Receipt for Your Wordlist: Why Every Dictionary Needs a Paper Trail

A Receipt for Your Wordlist: Why Every Dictionary Needs a Paper Trail

Security Testing 10.11.26
The Fireworks Are Over. The 250th Wordlist Is Just Getting Warm.

The Fireworks Are Over. The 250th Wordlist Is Just Getting Warm.

Security Testing 03.11.26
Two Letters, Zero Effort: How State Abbreviations and Area Codes Give Away Regional Passwords

Two Letters, Zero Effort: How State Abbreviations and Area Codes Give Away Regional Passwords