How letter pools are built

Every draw on this site comes from a pool, and every result tells you how large that pool was. The pool is what remains of the alphabet after a short, fixed sequence of stages — stages you control from the options on the main generator. This guide walks through them in the order the engine runs them, each one demonstrated by a real call to the drawing engine at build time, including the calls the engine refuses.

None of the demonstrations is typed in. Each example runs the same engine the live tools use, fed with scripted bytes so the page is reproducible, and the letters, pool sizes and error messages it returns are printed into the prose; every percentage is pool arithmetic computed from those reported sizes. Live draws use crypto.getRandomValues instead; see How a random letter is drawn and the rest of the guides.

The composition order

The engine composes a pool in exactly this order, every time, on every page:

  1. Alphabet — English (26 letters) or Greek (24 letters).
  2. Vowel or consonant filter — keeps one class of letters, or keeps them all.
  3. Include list — an intersection: only letters that are both in the pool so far and in your list survive.
  4. Exclude list — a subtraction: letters in your list are removed from whatever survived.
  5. Case expansion — uppercase forms, lowercase forms, or both, which doubles the pool.

The order matters because the stages do not commute: the include list is intersected with the filtered pool, not the whole alphabet, so a consonant in an include list disappears when the vowel filter is on; the exclude list runs after it, so a letter in both lists is excluded; and case comes last, which is why both lists are case-insensitive.

Stage one: the alphabet

The two alphabets are data tables inside the engine. The English table holds 26 letters, A to Z, each with an uppercase form, a lowercase form, a name and a vowel flag; the Greek table holds 24 letters, alpha through omega, with the same fields and names such as Alpha or Omega. With no other option set, the pool is the whole alphabet in uppercase: a plain draw reports a pool of 26, and the scripted byte 0 maps to A.

Stage two: the vowel or consonant filter

The filter keeps the letters whose vowel flag matches. In the English table the flagged vowels are A, E, I, O, U — 5 letters — so the vowel filter leaves a pool of 5: A E I O U. Every other letter in the table, Y included, is flagged as a consonant, so the consonant filter leaves 21: B C D F G H J K L M N P Q R S T V W X Y Z. Together the two filtered pools make up the whole 26-letter alphabet. The Greek table carries the same flag, with 7 vowels — Α Ε Η Ι Ο Υ Ω — and 17 consonants. The Vowel Generator and the Consonant Generator are this stage with the filter fixed.

Stage three: the include list is an intersection

An include list restricts the pool to the letters you type. The engine first parses the list: spaces, commas and semicolons are separators, and every remaining character must be a letter of the selected alphabet, in either case, or the whole draw is refused. The parsed letters form a set, and the pool becomes the intersection of that set with whatever the filter left. Typing x, y, z with the filter off gives a pool of 3 — X Y Z — in uppercase, because case is applied later. Typing A E B with the vowel filter on gives a pool of 2, A E: B is in the list but not in the vowel-filtered pool, so the intersection drops it — not an error, since the list said “only these” and the filter said “only vowels”.

Because the parsed list is a set, repeating a letter does nothing. A A A B is a pool of 2, not 4, and each letter in it is drawn with probability 1/2 — there is no way to weight a letter by listing it more than once. Validation is strict: A, 7 is refused with the message The include list contains “7”, which is not a letter of the selected alphabet. And Ω with the English alphabet selected is refused with The include list contains “Ω”, which is not a letter of the selected alphabet.

Stage four: the exclude list is a subtraction

An exclude list is parsed by the same rules and then subtracted. QXZ excluded from the full alphabet leaves 23; e excluded with the vowel filter on leaves 4: A I O U. Because exclusion runs after inclusion, a letter that appears in both lists is excluded: ABC included and B excluded gives A C, a pool of 2. A range such as A-Z is not understood — the hyphen is neither a separator nor a letter — and the draw is refused with The exclude list contains “-”, which is not a letter of the selected alphabet.

When nothing is left, and when one letter is left

The stages can remove everything. Vowels only, with aeiou excluded, leaves no letters, and the engine stops there: The selected filters leave no letters to draw from — relax the filters. Widening the pool quietly would hand you letters your own options ruled out. A pool of one letter is allowed, though. Include Q alone and the pool size is 1; a draw of 3 letters from it is Q Q Q, and the engine consumes no random bytes for it, because a span of one has nothing to choose.

Stage five: case expansion

Only now does case enter. The engine adds the uppercase form of every surviving letter if you asked for uppercase or both, then the lowercase form of each if you asked for lowercase or both. The pool is therefore ordered: every uppercase form in alphabet order, then every lowercase form. For the full alphabet with “both cases” that is a pool of 52, and the ordering shows in a scripted draw: bytes 0, 25, 26, 51 map to A Z a z, because index 0 is the first uppercase entry and index 26 is the first lowercase one.

This stage is worth stating precisely. “Both cases” is not an uppercase draw followed by a coin flip for case. It is one draw from a 52-entry pool in which A and a are separate entries, each at 1/52, about 1.9%. The consequences are visible: the result reports a pool of 52, not 26; a draw without repeats can contain both A and a, since removing one entry does not remove the other — a scripted unique draw of 2 from the mixed vowel pool returns A a; and the sampler reads 6 bits of each byte for this pool instead of 5, rejecting values from 52 to 63. The Uppercase & Lowercase Letters page fixes this stage.

Case expansion also explains why the lists are case-insensitive. X, Y, Z typed in capitals with lowercase selected gives x y z: the list chose the letters, and the case option then chose their form. With the vowel filter and both cases the pool has 10 entries, A E I O U a e i o u, of which 5 are uppercase — so the chance that a draw is uppercase is 5/10, or 50%, because the two halves of the pool are the same size.

Greek pools and Greek lists

The Greek alphabet goes through the same stages. Include and exclude lists must then contain Greek letters: alpha typed in Latin letters is refused — The include list contains “a”, which is not a letter of the selected alphabet. — because every character must be a glyph of the selected alphabet. The parser reads letters, never names, so a name spelled in Greek glyphs is taken as its letters: including αλφα gives a pool of 3, Α Λ Φ, not alpha. Lowercase sigma in the table is the medial form σ, but the final form ς is accepted in a list as sigma: including ς with lowercase selected gives a pool of 1 holding σ, named Sigma. The table itself is laid out in The Greek alphabet table, and the Greek Letter Generator draws from it unfiltered.

Reading the pool size in a result

Every result reports the pool it was drawn from and its size. The size is the denominator of every probability on this site: with a pool of n entries, each entry has probability exactly 1/n per draw, and nothing else — no letter frequency, no memory of earlier draws — adjusts that. A pool of 26 means 1/26, about 3.8%; the 5 vowels mean 1/5, or 20%; the 4-letter pool of vowels without E means 1/4, or 25%; the mixed pool of 52 means 1/52, about 1.9%. The pool size also caps draws without repeats. Ask for 6 unique vowels from a pool of 5 and the engine answers Cannot draw 6 letters without repeats from a pool of only 5 — allow repeats, lower the count, or widen the pool. The mechanics of that mode are in Drawing without repeats.

The pool size is also all the sampler needs: changing the pool changes how the random bytes are read, never how evenly the letters come out. Rejection sampling, explained covers that arithmetic.

Where the pool builder stops

The pool builder decides membership and nothing else. Every letter in the active pool is exactly equally likely — the engine never weights draws by English text frequency or any other distribution. There is no option for weights, and no page on this site will imply that one exists. The count field is separate from the pool: it asks for between 1 and 100 letters, and when repeats are allowed every one of them is an independent draw from the same, unchanged pool. That independence is why a small pool looks streaky — from the 4-letter pool, the second draw matches the first one time in 4 — and why streaks are no evidence against uniformity; see Uniform randomness and streaks. The engine builds the pool you asked for, reports its size, and draws from it uniformly.

Frequently asked questions

In what order are the pool options applied?

Always the same order: alphabet, vowel or consonant filter, include list (an intersection), exclude list (a subtraction), then case expansion. The include list is intersected with the filtered pool, exclusion runs after inclusion, and case is applied last — which is why both lists are case-insensitive.

Can I list a letter twice to make it more likely?

No. The include list is parsed into a set, so “A A A B” is a pool of 2 letters, not 4, and each is drawn with probability exactly 1/2. Every letter in the active pool is exactly equally likely — the engine never weights draws by English text frequency or any other distribution.

Why was my include or exclude list rejected?

Lists are validated against the alphabet you selected. Spaces, commas and semicolons are separators; every other character must be a letter of that alphabet, in either case. Digits, hyphen ranges and letters from the other alphabet are refused — “A, 7” is answered with: The include list contains “7”, which is not a letter of the selected alphabet. Nothing is silently dropped. A letter name is not recognised as a name: the parser reads it letter by letter, so it is accepted only when every character is a letter of the selected alphabet, and it then means those letters.

What does the result’s pool line show after an include list, an exclude list and both cases?

The pool the draw was actually taken from, and its size. Including “ABC”, excluding “B” and selecting both cases reports a pool of 4 — A C a c — the uppercase forms first, then the lowercase forms. Each entry is drawn at 1/4 (25%), so a given letter in either form has 2 entries out of 4, which is 1/2; draws without repeats treat A and a as different entries.

What happens if the filters remove every letter?

The draw is refused rather than quietly widened. Vowels only with “aeiou” excluded leaves nothing, and the engine answers: The selected filters leave no letters to draw from — relax the filters. A pool of one letter is allowed — every draw from it is that letter, and the result reports a pool of 1.

Does the pool size affect how the random bytes are used?

Yes, and only that. The sampler keeps the minimal bits that cover the pool — 3 for a pool of 5, 5 for 26, 6 for 52 — and rejects any value at or beyond the pool size before drawing again. A different pool changes how many bits are read and how often a value is rejected, never the fact that every entry is exactly equally likely.

Uniform means uniform: whatever pool the stages leave, every entry in it is drawn with equal probability — never weighted by English usage. Draws happen locally in your browser and are never transmitted. Details on the methodology page.