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 pyotpVerified import paths — ran on the pinned version, not inferred.
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).
Upgrade Python to 3.7 or newer, or pin `pyotp<2.8.0`.
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).
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.
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.
Review existing custom security-sensitive code paths for potential timing vulnerabilities.
Install the library using pip: `pip install pyotp`
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()`.
Provide a valid Base32 encoded secret key when initializing the TOTP/HOTP object, for example: `pyotp.TOTP('YOURBASE32SECRET')`.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()`.No dependency data recorded yet.