Random codes, passwords, tokens and PINs from a simple format string.
Describe the shape of the code you want — [a-z,0-9]{12} is twelve
lowercase letters or digits — and get a fresh batch every time you edit it.
Everything is generated in your browser with the
Web Crypto API;
nothing is sent to a server. Hit for the full syntax.
{{ errorContext.before }}{{ errorContext.at }}{{ errorContext.after }}
Format syntax
Square brackets pick a random character; curly braces say how many. Anything outside brackets is copied as-is.
[a-z] | Any character in a range |
[A,d,t,E,V] | Any of the listed characters |
[a-f,0-9] | Ranges and characters can be combined |
{5} | Exactly 5 characters (defaults to 1 if omitted) |
{2,10} | Between 2 and 10 characters, chosen per code |
[a-f,0-9]{4}-[0-9]{4} | The - between groups is literal |
\[ \] \, \- \\ | Inside brackets, [ ] , - \ have special meaning — put a backslash in front to use them as characters |
[\[, \], \,]{3} | Three characters chosen from [, ] and , |
[a-z,\-,\ ]{8} | Lowercase letters, hyphens and spaces (\ is an escaped space) |
\[[0-9]{3}\] | Outside brackets, escape [ and ] to print them: [482] |
The address bar always reflects the current settings, so you can bookmark or share
a link like ?format=[a-f,0-9]{32}&count=128&output=json —
see the FAQ for the parameters.
Enter a format above to generate codes.
FAQ
Is this secure enough for passwords, API keys and other secrets?
Yes, with the usual caveats about what you do with the result. Every character is
chosen with crypto.getRandomValues()
— the browser's cryptographically
secure random number generator, fed from the operating system's entropy source — and
picked uniformly using rejection sampling, so there's no modulo bias.
Nothing you generate leaves your browser. No server ever sees your format or your codes, there is no log of them, and there is no seed or session; the site cannot reproduce what it showed you, and neither can anyone else. That's also why knowing where a code came from doesn't help an attacker: someone who knew you used rng.codes, and even guessed the format, would still face the full search space — exactly as if you had rolled dice.
What the site can't protect is what happens after you copy. Clipboard managers keep history, browser extensions can read the page, and a 4-digit PIN is still only a 4-digit PIN no matter how randomly it was chosen.
Where does the randomness come from? Why not Math.random()?
Math.random() is a fast generator meant for games and animations. Its
output can be predicted from enough previous values, and it was never intended for
secrets. crypto.getRandomValues() is the
Web Crypto API's
generator and is designed for exactly this. For each character a 32-bit value is drawn; values that
would skew the result are discarded so that every character in your set is equally
likely. The whole thing is a dozen lines in format.js.
How strong is a code?
Strength is the size of the search space. A set of N characters repeated L times gives NL possibilities, or L × log2(N) bits. A rough guide:
[0-9]{6}— 106, about 20 bits. Fine for a one-time PIN, not a password.[a-z,0-9]{12}— 3612, about 62 bits.[a-z,A-Z,0-9]{16}— 6216, about 95 bits.[a-f,0-9]{32}— 1632, 128 bits. Comparable to a 128-bit key.
The readout under the input shows this figure for the current format. For a
variable length such as {8,12} it shows a range, from the shortest code
the format can produce to the longest — the short end is what an attacker would try
first. Listing a character more than once, such as [a-f,a-z], doesn't add
strength: it makes those characters more likely, which slightly lowers it, and the
readout accounts for that.
What does the site store or send?
The app itself sends nothing: your format and your codes never leave the page. The only things it remembers are your last format, count and output mode, kept in your browser's localStorage so they're there when you come back.
The site is served through Cloudflare, which may add its own lightweight, cookieless performance and analytics beacons — page views, load times, that sort of thing. Those are used to see whether the site works and roughly how busy it is, nothing more. There is no advertising, no cross-site tracking and no fingerprinting, and nothing that connects a visit to you or to what you generated.
Can I link to a particular format?
Yes. The address bar always reflects the current format, count and output, so bookmarking the page or copying its URL captures exactly what you're looking at. Only settings that differ from the defaults appear. The parameters are:
format | The format string, e.g. ?format=[a-f,0-9]{32} |
count | How many codes to generate: any whole number from 1 to 1024 (default 64); larger values are capped at 1024 |
output | list for the grid (default), text for one per line, or json for an array |
For example, ?format=[A-Z,0-9]{5}-[A-Z,0-9]{5}&count=32&output=text
gives 32 serial-style keys as plain text. Brackets, braces and commas can be typed
as they are. If you write a link by hand, characters that mean something in a URL
need percent-encoding: & as %26, # as
%23, % as %25 and + as
%2B (a bare + is read as a space). Links copied from the
address bar are already encoded.
Is there an API?
Yes — a small HTTP endpoint for scripts and other programs, separate from the page you're looking at. It takes the same parameters as the URL above:
format | Required. The format string, e.g. [a-f,0-9]{32} |
count | Same as the page: 1 to 1024, default 64, larger values capped |
output | json (default) for an array plus the entropy estimate, or text for one code per line |
{{ apiCurlExample }}
The -g isn't optional: curl's own URL globbing treats [ ]
and { } as its own range syntax, and every format string is made of
them — drop it and curl fails with "bad range in URL" instead of making the
request. Other tools and languages don't do this; it's specifically a curl thing.
returns
{"format":"[a-f,0-9]{32}","count":5,"entropy":{"min":128,"max":128},"codes":[...]}
No API key or signup — just don't script past the rate limit, 30 requests per 10
seconds per IP; going over it gets a 429 until the window clears. A bad
format string returns 400 with the same error a broken format shows on
the page.
One real difference from the page: this means a server generates the codes, not your browser. The API runs on a small Cloudflare Worker that never logs or stores anything and forgets each request the moment it's answered — but it does briefly see your format string and the codes it returns, which the page's own generator never does. For anything sensitive, use the page.
Can I read the code?
Please do — that's part of the point. It's three plain files with no build step:
index.html (this page), format.js (the parser and generator)
and app.js (the Vue app). View source and the comments in each file
explain how it all works, or
download the code
— a zip of the whole site with its libraries, tests and a README, ready to serve
from any folder.