Skip to content

Generate Random Bytes

Generate cryptographically secure random bytes for keys, nonces, salts, secrets and API tokens. Up to 4,096 bytes per set and 100 sets at once, as hex, Base64, Base64url, decimal, or ready-to-paste C, Python, JavaScript, Go and Rust literals.

Generated in your browser with crypto.getRandomValues()

Changing the format rewrites the same bytes
Bytes each
32
Random bits each
256
Characters each
…
Sets
1

    How Many Bytes for Keys, Nonces, Salts and Tokens

    Every random byte adds 8 bits of unpredictability. These are the sizes the standards ask for; the presets above set them for you.

    Recommended random byte lengths by purpose
    PurposeBytesWhy that size
    AES-128 key16The key is exactly 128 bits
    AES-256 key32The key is exactly 256 bits
    AES-GCM nonce (IV)12NIST SP 800-38D recommends 96-bit IVs
    ChaCha20-Poly1305 nonce12RFC 8439 uses a 96-bit nonce
    HMAC-SHA-256 / JWT HS256 secret32 or moreRFC 7518: at least the hash size, 256 bits
    Password-hash salt16 or moreNIST SP 800-132: at least 128 random bits
    Session ID16 is typicalOWASP: at least 64 bits of entropy; 128 leaves a wide margin
    API key or bearer token24 to 32Far beyond guessing; 24 bytes is 32 Base64url characters

    A random byte string isn't the same as a password: people can't remember it, and it is meant to be stored by software. For a password, use the random string generator.

    Bytes vs Characters: Hex, Base64 and Base64url

    The most common mistake with random keys is mixing up bytes and characters. Hex writes each byte as 2 characters. Base64 writes every 3 bytes as 4 characters, padding the end with =. Base64url uses - and _ instead of + and / so it is safe in URLs and file names, and usually drops the padding.

    hex = 2n  ·  Base64 = 4 × ⌈n ÷ 3⌉  ·  Base64url (no padding) = ⌈4n ÷ 3⌉
    Characters produced by common byte lengths in each encoding
    BytesHexBase64Base64url
    12241616
    163224 (ends ==)22
    24483232
    326444 (ends =)43
    6412888 (ends ==)86

    So when a setting asks for "a 32-character key", check what it means. If it decodes hex, 32 characters is only 16 bytes (128 bits). If it uses the characters as they are, 32 hex characters carry 128 bits of randomness, not 256, because each hex character only holds 4 bits. Lengths that are a multiple of 3 bytes (12, 24) never need Base64 padding.

    Worked Example: A Secret for JWT HS256

    An app signs login tokens with HS256 and the security review says the current secret, mysecret123, is too weak. What should replace it?

    Step 1: Minimum size

    HS256 uses SHA-256 → RFC 7518 requires a key of at least 256 bits = 32 bytes

    Step 2: Generate and encode

    Preset "JWT HS256 secret" → 32 bytes → 43 Base64url characters

    Step 3: Store it as configuration, not code

    JWT_SECRET=<the 43 characters> in the secret manager or .env

    Check whether your library decodes the string or uses its text. Some decode Base64 to get the 32 bytes back; many simply use the characters' UTF-8 bytes as the key. Either way the 43 characters carry the full 256 bits, so it's safe, but the two settings are not interchangeable: a token signed by one service won't verify on another that treats the secret differently. Changing the secret signs everyone out, so plan the rotation.

    Bytes Ready to Paste Into Code

    For test vectors, fixed fixtures or embedded firmware you often want the bytes as a literal rather than a string. Pick a code format and the same bytes are rewritten in that syntax. Here are the same four bytes, de ad be ef, in each:

    The bytes de ad be ef as literals in several languages
    LanguageLiteral
    C / C++unsigned char k[] = { 0xde, 0xad, 0xbe, 0xef };
    Pythonk = b'\xde\xad\xbe\xef'
    JavaScriptconst k = new Uint8Array([0xde, 0xad, 0xbe, 0xef]);
    Gok := []byte{0xde, 0xad, 0xbe, 0xef}
    Rustlet k: [u8; 4] = [0xde, 0xad, 0xbe, 0xef];

    Don't commit a real production key as a literal; anything in source control should be treated as public. Literals are for tests and examples. For bit-level practice values rather than whole bytes, use the random binary number generator.

    The Same Bytes From a Terminal

    Each of these prints 32 random bytes from the operating system's secure generator.

    # OpenSSL (Linux, macOS, Git Bash)
    openssl rand -hex 32
    openssl rand -base64 32
    
    # Linux / macOS without OpenSSL
    head -c 32 /dev/urandom | base64
    
    # Python
    python3 -c "import secrets; print(secrets.token_hex(32))"
    python3 -c "import secrets; print(secrets.token_urlsafe(32))"
    
    # Node.js 16 or later
    node -e "console.log(require('crypto').randomBytes(32).toString('base64url'))"
    
    # PowerShell 7.2 or later
    [Convert]::ToBase64String([Security.Cryptography.RandomNumberGenerator]::GetBytes(32))

    Note that secrets.token_hex(32) and openssl rand -hex 32 take a byte count and print 64 characters, while token_urlsafe(32) prints 43.

    Is It Safe to Make Keys in a Browser?

    The randomness is fine. crypto.getRandomValues() is the browser's cryptographically secure generator, seeded by the operating system, and this page creates the bytes on your device without sending them anywhere. The risks come afterwards, from where the value travels:

    • Clipboard and screens. Clipboard history, screen sharing and screenshots can all keep a copy. Paste straight into its destination and clear the clipboard.
    • Chat and tickets. A key pasted into Slack or an issue tracker should be considered exposed. Share secrets through a secret manager.
    • Production keys. Where you can, generate keys inside the system that stores them (a cloud KMS, Vault, or the server's own openssl) so they never pass through a desktop at all.

    One rule matters more than size for AES-GCM: never reuse a nonce with the same key. Reuse lets an attacker recover data and forge messages. With random 12-byte nonces, NIST SP 800-38D limits one key to 2³² (about 4.3 billion) encryptions, so a fresh nonce from here is fine for occasional manual use but your code should generate one per message.

    Frequently asked questions

    Why does my Base64 output end in = or ==?

    Base64 encodes 3 bytes at a time. If the length isn’t a multiple of 3, the last group is padded with one or two = signs. Base64url output here drops them, as JWTs and most URL tokens do.

    How is this different from a UUID?

    A version 4 UUID is 16 random bytes with 6 bits overwritten to mark the version and variant, leaving 122 random bits, written in a fixed hex format. Raw bytes keep every bit random and let you choose the length and encoding.

    Can I get the same bytes again?

    No. Nothing is stored or seeded, so copy or download a value before pressing Generate new. Changing only the output format keeps the current bytes.

    What is the .bin download for?

    It saves the raw bytes, not text, for programs, tests and firmware builds that load a key from a binary file. With several sets, they are joined end to end in one file.

    Sources