os.urandom

The OS cryptographic random source as bytes: /dev/urandom or the getrandom() syscall on Linux, BCryptGenRandom() on Windows. Available everywhere; os.getrandom() and its GRND_* flags are Linux only (Linux 3.17+). For tokens and passwords use the secrets module, which is built on the same source.

os functionPython 3.0+ (getrandom 3.6+)
Common call
os.urandom(16)
Returns
bytes of length 16, different on every call
Replaces
random.getrandbits / random.randbytes for anything secret
Watch out
It returns bytes, not text: use .hex() or secrets.token_hex()
os.urandom(sizesize — Number of bytes. 0 gives b"", a negative size raises ValueError.type: int · required, /)
→ bytes

Parameters

NameTypeRequiredDescription
sizeintyesNumber of bytes. 0 gives b"", a negative size raises ValueError.
flagsintno (0)os.getrandom() only: GRND_NONBLOCK (raise BlockingIOError instead of blocking) and/or GRND_RANDOM (read from the /dev/random pool), OR-ed together.

Return value

bytes — Exactly size bytes from the OS randomness source.

Common patterns

A random key or salt
Bytes straight from the OS, the input that hashlib.pbkdf2_hmac and friends expect.
import hashlib, os
salt = os.urandom(16)
key = hashlib.pbkdf2_hmac('sha256', b'password', salt, 600_000)
Text tokens with secrets
secrets turns the same OS randomness into hex or URL-safe text.
import secrets
reset_token = secrets.token_urlsafe(32)
api_key = secrets.token_hex(20)
Non-blocking read on Linux
GRND_NONBLOCK makes getrandom raise BlockingIOError instead of waiting for the entropy pool at early boot.
import os
try:
    seed = os.getrandom(32, os.GRND_NONBLOCK)
except BlockingIOError:
    seed = None  # pool not initialised yet

Examples

1. bytes of the requested length
import os b = os.urandom(16) (type(b).__name__, len(b))
Returns
('bytes', 16)
2. Zero bytes is allowed
import os os.urandom(0)
Returns
b''
3. Two calls differ
import os os.urandom(8) == os.urandom(8)
Returns
False
4. As an unsigned integer
import os int.from_bytes(os.urandom(4), 'big') < 2**32
Returns
True
5. secrets: 16 bytes as 32 hex characters
import secrets len(secrets.token_hex(16))
Returns
32
6. secrets: URL-safe text token
import secrets t = secrets.token_urlsafe(32) (type(t).__name__, len(t))
Returns
('str', 43)
7. Negative size
import os os.urandom(-1)
Returns
ValueError: negative argument not allowed

Pitfalls

1. Using the random module for secrets
random is a seeded Mersenne Twister: anyone who learns or guesses the seed reproduces every value. Tokens, salts and keys must come from os.urandom / secrets.
random.Random
import random
random.Random(1).randbytes(8) == random.Random(1).randbytes(8)
True
secrets / os.urandom
import secrets
secrets.token_bytes(8) == secrets.token_bytes(8)
False
2. Turning the bytes into text with str()
str() of bytes gives the repr with b and escapes, not a usable token. Encode with .hex() or base64, or use secrets.token_hex directly.
str(bytes)
str(b'\x00\xff')
"b'\\x00\\xff'"
.hex()
b'\x00\xff'.hex()
'00ff'
3. Passing a float size
size must be an int; compute it with // or int() first.
bits / 8
import os
os.urandom(20 / 8)
TypeError: 'float' object cannot be interpreted as an integer
bits // 8
import os
len(os.urandom(256 // 8))
32

When to use

Use it
  • Keys, salts, nonces and IVs for cryptographic code
  • Seeding your own generator from a source nobody can predict
Reach for something else
  • Text tokens, passwords, choices from an alphabet → secrets.token_urlsafe / token_hex / secrets.choice
  • Reproducible simulations and tests → random.Random(seed)
  • Random numbers in a range → secrets.randbelow or random.SystemRandom

Notes

CPython impl
Linux: getrandom() syscall in blocking mode (waits only until the kernel entropy pool is initialised, PEP 524); other Unix: /dev/urandom (NotImplementedError if it is missing); Windows: BCryptGenRandom() since 3.11
Availability
urandom: Unix, Windows. getrandom and GRND_NONBLOCK / GRND_RANDOM: Linux 3.17+ only, added in 3.6 (on Linux GRND_NONBLOCK == 1 and GRND_RANDOM == 2)
getrandom
May return fewer bytes than requested; with GRND_NONBLOCK it raises BlockingIOError instead of blocking. Reading large amounts drains the pool other users share, so prefer urandom
secrets
secrets.token_bytes / token_hex / token_urlsafe / randbelow / choice and random.SystemRandom all draw from os.urandom

FAQ

Yes. It reads the operating system CSPRNG (getrandom()/dev/urandom on Linux, BCryptGenRandom on Windows), which is what the docs describe as suitable for cryptographic use. The examples on this page only check lengths and types because the bytes are different on every run.