# `!secrets` --- Generate secure random numbers for managing secrets

<div class="module" data-synopsis="Generate secure random numbers for managing secrets.">

secrets

</div>

<div class="versionadded">

3.6

</div>

<div class="testsetup">

from secrets import \* \_\_name\_\_ = '\<doctest\>'

</div>

**Source code:** `Lib/secrets.py`

------------------------------------------------------------------------

The `!secrets` module is used for generating cryptographically strong random numbers suitable for managing data such as passwords, account authentication, security tokens, and related secrets.

In particular, `!secrets` should be used in preference to the default pseudo-random number generator in the `random` module, which is designed for modelling and simulation, not security or cryptography.

<div class="seealso">

`506`

</div>

## Random numbers

The `!secrets` module provides access to the most secure source of randomness that your operating system provides.

<div class="SystemRandom">

A class for generating random numbers using the highest-quality sources provided by the operating system. See `random.SystemRandom` for additional details.

</div>

<div class="function">

choice(seq)

Return a randomly chosen element from a non-empty sequence.

</div>

<div class="function">

randbelow(exclusive_upper_bound)

Return a random int in the range \[0, *exclusive_upper_bound*).

</div>

<div class="function">

randbits(k)

Return a non-negative int with *k* random bits.

</div>

## Generating tokens

The `!secrets` module provides functions for generating secure tokens, suitable for applications such as password resets, hard-to-guess URLs, and similar.

<div class="function">

token_bytes(nbytes=None)

Return a random byte string containing *nbytes* number of bytes.

If *nbytes* is not specified or `None`, `DEFAULT_ENTROPY` is used instead.

<div class="doctest">

\>\>\> token_bytes(16) \# doctest: +SKIP b'xebrx17D\*txaexd4xe3Sxb6xe2xebP1x8b'

</div>

</div>

<div class="function">

token_hex(nbytes=None)

Return a random text string, in hexadecimal. The string has *nbytes* random bytes, each byte converted to two hex digits.

If *nbytes* is not specified or `None`, `DEFAULT_ENTROPY` is used instead.

<div class="doctest">

\>\>\> token_hex(16) \# doctest: +SKIP 'f9bf78b9a18ce6d46a0cd2b0b86df9da'

</div>

</div>

<div class="function">

token_urlsafe(nbytes=None)

Return a random URL-safe text string, containing *nbytes* random bytes. The text is Base64 encoded, so on average each byte results in approximately 1.3 characters.

If *nbytes* is not specified or `None`, `DEFAULT_ENTROPY` is used instead.

<div class="doctest">

\>\>\> token_urlsafe(16) \# doctest: +SKIP 'Drmhze6EPcv0fN_81Bj-nA'

</div>

</div>

### How many bytes should tokens use?

To be secure against [brute-force attacks](https://en.wikipedia.org/wiki/Brute-force_attack), tokens need to have sufficient randomness. Unfortunately, what is considered sufficient will necessarily increase as computers get more powerful and able to make more guesses in a shorter period. As of 2015, it is believed that 32 bytes (256 bits) of randomness is sufficient for the typical use-case expected for the `!secrets` module.

For those who want to manage their own token length, you can explicitly specify how much randomness is used for tokens by giving an `int` argument to the various `token_*` functions. That argument is taken as the number of bytes of randomness to use.

Otherwise, if no argument is provided, or if the argument is `None`, the `token_*` functions use `DEFAULT_ENTROPY` instead.

<div class="data">

DEFAULT_ENTROPY

Default number of bytes of randomness used by the `token_*` functions.

The exact value is subject to change at any time, including during maintenance releases.

</div>

## Other functions

<div class="function">

compare_digest(a, b)

Return `True` if strings or `bytes-like objects <bytes-like object>` *a* and *b* are equal, otherwise `False`, using a "constant-time compare" to reduce the risk of [timing attacks](https://web.archive.org/web/20250815071532/https://codahale.com/a-lesson-in-timing-attacks/). See `hmac.compare_digest` for additional details.

</div>

## Recipes and best practices

This section shows recipes and best practices for using `!secrets` to manage a basic level of security.

Generate an eight-character alphanumeric password:

<div class="testcode">

import string import secrets alphabet = string.ascii_letters + string.digits password = ''.join(secrets.choice(alphabet) for i in range(8))

</div>

> [!NOTE]
> Applications should not `store passwords in a recoverable format <257>`, whether plain text or encrypted. They should be salted and hashed using a cryptographically strong one-way (irreversible) hash function.

Generate a ten-character alphanumeric password with at least one lowercase character, at least one uppercase character, and at least three digits:

<div class="testcode">

import string import secrets alphabet = string.ascii_letters + string.digits while True: password = ''.join(secrets.choice(alphabet) for i in range(10)) if (any(c.islower() for c in password) and any(c.isupper() for c in password) and sum(c.isdigit() for c in password) \>= 3): break

</div>

Generate an [XKCD-style passphrase](https://xkcd.com/936/):

<div class="testcode">

import secrets \# On standard Linux systems, use a convenient dictionary file. \# Other platforms may need to provide their own word-list. with open('/usr/share/dict/words') as f: words = \[word.strip() for word in f\] password = ' '.join(secrets.choice(words) for i in range(4))

</div>

Generate a hard-to-guess temporary URL containing a security token suitable for password recovery applications:

<div class="testcode">

import secrets url = 'https://example.com/reset=' + secrets.token_urlsafe()

</div>