Registry / auth-security / pyotp
library2.10.0pypypi✓ verified 27d ago

PyOTP is a Python library for generating and verifying one-time passwords, supporting both Time-Based One-Time Passwords (TOTP) from RFC 6238 and HMAC-Based One-Time Passwords (HOTP) from RFC 4226. It is widely used to implement two-factor (2FA) or multi-factor (MFA) authentication in various systems, compatible with apps like Google Authenticator. The library is actively maintained, with its current version being 2.9.0, and follows a regular release cadence.

pip install pyotp
INSTALL
IMPORT
SIG · PYOTP
P
pyotp
auth-securitypythonv2.10.0
Install
1.6s avg
Import
39ms
Disk
16MB
Pass rate
10/ 10
Env Coverage10 / 10
glibc
3.93.13
musl
3.93.13
Install & Compatibility
Where this runs
tested against v2.10.0 · pip install
no network on importno background threads
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
musl
py 3.103.95 runs
installs and imports cleanly · install 0.0s · import 0.040s · 17.9MB
glibc
py 3.103.95 runs
installs and imports cleanly · install 1.6s · import 0.038s · 18MB
16MB installed
● package 16MB
Code
Verified usage

Verified import paths — ran on the pinned version, not inferred.

TOTP
from pyotp import TOTP
HOTP
from pyotp import HOTP
random_base32
import pyotp secret = pyotp.random_base32()
random_hex
import pyotp secret = pyotp.random_hex()
parse_uri
import pyotp otp_object = pyotp.parse_uri(uri_string)

This quickstart demonstrates how to generate a random secret, create a Time-Based One-Time Password (TOTP) object, generate a provisioning URI for client applications (like Google Authenticator), and then verify an OTP. It also shows a basic example for HMAC-Based One-Time Passwords (HOTP).

import pyotp import time # Generate a random base32 secret key secret = pyotp.random_base32() print(f"Generated Secret: {secret}") # Create a TOTP object totp = pyotp.TOTP(secret) # Generate a provisioning URI for Google Authenticator (or similar) # In a real app, 'alice@example.com' would be the user's email # 'SecureApp' would be the name of your application uri = totp.provisioning_uri(name="alice@example.com", issuer_name="SecureApp") print(f"Provisioning URI: {uri}") # In a real application, you'd render this URI as a QR code for the user to scan. # For demonstration, we'll manually get a code. # Simulate getting an OTP code from the user (e.g., from their authenticator app) current_otp = totp.now() print(f"Current OTP (will change every 30s): {current_otp}") # Verify the OTP code # You might wait a few seconds to demonstrate validity windows # user_input_otp = input("Enter the OTP from your authenticator app: ") user_input_otp = current_otp # For demonstration, assume correct input if totp.verify(user_input_otp): print("OTP verified successfully!") else: print("Invalid OTP.") # For HOTP (counter-based): hotp = pyotp.HOTP(secret) initial_count = 0 first_hotp = hotp.at(initial_count) print(f"HOTP for count {initial_count}: {first_hotp}") # Verify HOTP # In a real app, you'd store and increment the counter after each successful verification if hotp.verify(first_hotp, initial_count): print("HOTP verified successfully!")
Debug
Known issues
breakingPython 3.6 support was dropped in pyotp v2.8.0. Users on Python 3.6 or older must upgrade their Python environment or pin pyotp to a version prior to 2.8.0.
fix
Upgrade Python to 3.7 or newer, or pin `pyotp<2.8.0`.
affects: >=2.8.0
breakingThe default and minimum secret lengths were increased in versions 2.5.0 (base32 to 26 chars) and 2.6.0 (base32 to 32 chars, hex to 40 chars) to meet RFC recommendations. Versions 2.4.0 and later will raise an error if a secret is too short. Applications relying on implicitly generated or shorter secrets from older versions might encounter errors.
fix
Ensure that all generated or provided secrets meet the new minimum length requirements (e.g., `pyotp.random_base32()` for 32 characters or `pyotp.random_hex()` for 40 characters).
affects: >=2.4.0
gotchaTo prevent replay attacks, the RFCs and `pyotp` documentation recommend storing the most recently authenticated timestamp, OTP, or a hash of the OTP in your database and rejecting any OTP that has been used before.
fix
Implement server-side tracking of used OTPs or timestamps to prevent reuse. For TOTP, `TOTP.verify()` takes a `valid_window` parameter to allow for clock drift, but this does not prevent replay attacks without additional server-side state.
affects: All
gotchaFor TOTP, accurate time synchronization between the server and the client (authenticator app) is crucial. Significant clock drift can lead to OTPs being incorrectly rejected.
fix
Ensure your server's clock is synchronized using NTP. When verifying TOTPs, consider using the `valid_window` parameter in `totp.verify()` to allow for minor clock discrepancies.
affects: All
gotchaAs of v2.8.0, OTP generation runs in constant time to mitigate timing side-channel attacks. While this is a security improvement, ensure any custom OTP generation or verification logic in your application also considers constant-time operations if sensitive to such attacks.
fix
Review existing custom security-sensitive code paths for potential timing vulnerabilities.
affects: All
Errors
Common errors & fixes
ModuleNotFoundError: No module named 'pyotp'
The 'pyotp' library has not been installed in the current Python environment.
fix
Install the library using pip: `pip install pyotp`
ValueError: Not a base32 string
The secret key provided to `pyotp.TOTP()` or `pyotp.HOTP()` is not a valid Base32 encoded string, which is required by the library.
fix
Ensure the secret key is properly Base32 encoded. You can generate a valid one using `pyotp.random_base32()` or encode an existing string using `base32.b32encode()`.
TypeError: TOTP.__init__() missing 1 required positional argument: 's'
The `pyotp.TOTP` (or `pyotp.HOTP`) class constructor requires a secret key (argument `s`) to be provided when an instance is created.
fix
Provide a valid Base32 encoded secret key when initializing the TOTP/HOTP object, for example: `pyotp.TOTP('YOURBASE32SECRET')`.
AttributeError: module 'pyotp' has no attribute 'now'
The `now()` method is an instance method of `pyotp.TOTP` and needs to be called on an instantiated `TOTP` object, not directly on the `pyotp` module or the `TOTP` class.
fix
First create a `TOTP` object with a secret key, then call `now()` on that object: `totp_obj = pyotp.TOTP('BASE32SECRET'); current_otp = totp_obj.now()`.
Upgrade
Version history
2.10.0latest on PyPI · released Jun 14, 2026
Audit
Dependencies

No dependency data recorded yet.

Agent activity
17 hits · last 30 days
node
14
Amazon
1
OpenAI (training)
1
Resources
pyotp — pip install pyotp · libregistry