PyOTP - The Python One-Time Password Library
********************************************

PyOTP is a Python library for generating and verifying one-time
passwords. It can be used to implement two-factor (2FA) or multi-
factor (MFA) authentication methods in web applications and in other
systems that require users to log in.

Open MFA standards are defined in RFC 4226 (HOTP: An HMAC-Based One-
Time Password Algorithm) and in RFC 6238 (TOTP: Time-Based One-Time
Password Algorithm). PyOTP implements server-side support for both of
these standards. Client-side support can be enabled by sending
authentication codes to users over SMS or email (HOTP) or, for TOTP,
by instructing users to use Google Authenticator, Authy, or another
compatible app. Users can set up auth tokens in their apps easily by
using their phone camera to scan otpauth:// QR codes provided by
PyOTP.

Implementers should read and follow the HOTP security requirements and
TOTP security considerations sections of the relevant RFCs. At
minimum, application implementers should follow this checklist:

* Ensure transport confidentiality by using HTTPS

* Ensure HOTP/TOTP secret confidentiality by storing secrets in a
  controlled access database

* Deny replay attacks by rejecting one-time passwords that have been
  used by the client (this requires storing the most recently
  authenticated timestamp, OTP, or hash of the OTP in your database,
  and rejecting the OTP when a match is seen)

* Throttle (rate limit) brute-force attacks against your application's
  login functionality (see RFC 4226, section 7.3)

* When implementing a "greenfield" application, consider supporting
  FIDO U2F/WebAuthn in addition to or instead of HOTP/TOTP. U2F uses
  asymmetric cryptography to avoid using a shared secret design, which
  strengthens your MFA solution against server-side attacks. Hardware
  U2F also sequesters the client secret in a dedicated single-purpose
  device, which strengthens your clients against client-side attacks.
  And by automating scoping of credentials to relying party IDs
  (application origin/domain names), U2F adds protection against
  phishing attacks. One implementation of FIDO U2F/WebAuthn is PyOTP's
  sister project, PyWARP.

We also recommend that implementers read the OWASP Authentication
Cheat Sheet and NIST SP 800-63-3: Digital Authentication Guideline for
a high level overview of authentication best practices.


Quick overview of using One Time Passwords on your phone
========================================================

* OTPs involve a shared secret, stored both on the phone and the
  server

* OTPs can be generated on a phone without internet connectivity

* OTPs should always be used as a second factor of authentication (if
  your phone is lost, you account is still secured with a password)

* Google Authenticator and other OTP client apps allow you to store
  multiple OTP secrets and provision those using a QR Code


Installation
============

   pip install pyotp


Usage
=====


Time-based OTPs
---------------

   import pyotp
   import time

   totp = pyotp.TOTP('base32secret3232')
   totp.now() # => '492039'

   # OTP verified for current time
   totp.verify('492039') # => True
   time.sleep(30)
   totp.verify('492039') # => False


Counter-based OTPs
------------------

   import pyotp

   hotp = pyotp.HOTP('base32secret3232')
   hotp.at(0) # => '260182'
   hotp.at(1) # => '055283'
   hotp.at(1401) # => '316439'

   # OTP verified with a counter
   hotp.verify('316439', 1401) # => True
   hotp.verify('316439', 1402) # => False


Generating a Secret Key
-----------------------

A helper function is provided to generate a 32-character base32
secret, compatible with Google Authenticator and other OTP apps:

   pyotp.random_base32()

Some applications want the secret key to be formatted as a hex-encoded
string:

   pyotp.random_hex()  # returns a 40-character hex-encoded secret


Google Authenticator Compatible
-------------------------------

PyOTP works with the Google Authenticator iPhone and Android app, as
well as other OTP apps like Authy. PyOTP includes the ability to
generate provisioning URIs for use with the QR Code scanner built into
these MFA client apps:

   pyotp.totp.TOTP('JBSWY3DPEHPK3PXP').provisioning_uri(name='alice@google.com', issuer_name='Secure App')

   >>> 'otpauth://totp/Secure%20App:alice%40google.com?secret=JBSWY3DPEHPK3PXP&issuer=Secure%20App'

   pyotp.hotp.HOTP('JBSWY3DPEHPK3PXP').provisioning_uri(name="alice@google.com", issuer_name="Secure App", initial_count=0)

   >>> 'otpauth://hotp/Secure%20App:alice%40google.com?secret=JBSWY3DPEHPK3PXP&issuer=Secure%20App&counter=0'

This URL can then be rendered as a QR Code (for example, using
https://github.com/soldair/node-qrcode) which can then be scanned and
added to the users list of OTP credentials.

Parsing these URLs is also supported:

   pyotp.parse_uri('otpauth://totp/Secure%20App:alice%40google.com?secret=JBSWY3DPEHPK3PXP&issuer=Secure%20App')

   >>> <pyotp.totp.TOTP object at 0xFFFFFFFF>

   pyotp.parse_uri('otpauth://hotp/Secure%20App:alice%40google.com?secret=JBSWY3DPEHPK3PXP&issuer=Secure%20App&counter=0'

   >>> <pyotp.totp.HOTP object at 0xFFFFFFFF>


Working example
---------------

Scan the following barcode with your phone's OTP app (e.g. Google
Authenticator):

[image]

Now run the following and compare the output:

   import pyotp
   totp = pyotp.TOTP("JBSWY3DPEHPK3PXP")
   print("Current OTP:", totp.now())


Third-party contributions
-------------------------

The following third-party contributions are not described by a
standard, not officially supported, and provided for reference only:

* "pyotp.contrib.Steam()": An implementation of Steam TOTP. Uses the
  same API as *pyotp.TOTP()*.


Links
-----

* Project home page (GitHub)

* Documentation

* Package distribution (PyPI)

* Change log

* RFC 4226: HOTP: An HMAC-Based One-Time Password

* RFC 6238: TOTP: Time-Based One-Time Password Algorithm

* ROTP - Original Ruby OTP library by Mark Percival

* OTPHP - PHP port of ROTP by Le Lag

* OWASP Authentication Cheat Sheet

* NIST SP 800-63-3: Digital Authentication Guideline

For new applications:

* WebAuthn

* PyWARP


Versioning
----------

This package follows the Semantic Versioning 2.0.0 standard. To
control changes, it is recommended that application developers pin the
package version and manage it using pip-tools or similar. For library
developers, pinning the major version is recommended.

[image][image][image][image][image]


API documentation
*****************

pyotp.parse_uri(uri: str) -> OTP

   Parses the provisioning URI for the OTP; works for either TOTP or
   HOTP.

   See also:
      https://github.com/google/google-authenticator/wiki/Key-Uri-
      Format

   Parameters:
      **uri** -- the hotp/totp URI to parse

   Returns:
      OTP object

class pyotp.totp.TOTP(s: str, digits: int = 6, digest: Any = None, name: str | None = None, issuer: str | None = None, interval: int = 30)

   Handler for time-based OTP counters.

   at(for_time: int | datetime, counter_offset: int = 0) -> str

      Accepts either a Unix timestamp integer or a datetime object.

      To get the time until the next timecode change (seconds until
      the current OTP expires), use this instead:

         totp = pyotp.TOTP(...)
         time_remaining = totp.interval - datetime.datetime.now().timestamp() % totp.interval

      Parameters:
         * **for_time** -- the time to generate an OTP for

         * **counter_offset** -- the amount of ticks to add to the
           time counter

      Returns:
         OTP value

   now() -> str

      Generate the current time OTP

      Returns:
         OTP value

   provisioning_uri(name: str | None = None, issuer_name: str | None = None, **kwargs) -> str

      Returns the provisioning URI for the OTP.  This can then be
      encoded in a QR Code and used to provision an OTP app like
      Google Authenticator.

      See also:
         https://github.com/google/google-authenticator/wiki/Key-Uri-
         Format

   timecode(for_time: datetime) -> int

      Accepts either a timezone naive (*for_time.tzinfo is None*) or a
      timezone aware datetime as argument and returns the
      corresponding counter value (timecode).

   verify(otp: str, for_time: datetime | None = None, valid_window: int = 0) -> bool

      Verifies the OTP passed in against the current time OTP.

      Parameters:
         * **otp** -- the OTP to check against

         * **for_time** -- Time to check OTP at (defaults to now)

         * **valid_window** -- extends the validity to this many
           counter ticks before and after the current one

      Returns:
         True if verification succeeded, False otherwise

class pyotp.hotp.HOTP(s: str, digits: int = 6, digest: Any = None, name: str | None = None, issuer: str | None = None, initial_count: int = 0)

   Handler for HMAC-based OTP counters.

   at(count: int) -> str

      Generates the OTP for the given count.

      Parameters:
         **count** -- the OTP HMAC counter

      Returns:
         OTP

   provisioning_uri(name: str | None = None, initial_count: int | None = None, issuer_name: str | None = None, **kwargs) -> str

      Returns the provisioning URI for the OTP.  This can then be
      encoded in a QR Code and used to provision an OTP app like
      Google Authenticator.

      See also:
         https://github.com/google/google-authenticator/wiki/Key-Uri-
         Format

      Parameters:
         * **name** -- name of the user account

         * **initial_count** -- starting HMAC counter value, defaults
           to 0

         * **issuer_name** -- the name of the OTP issuer; this will be
           the organization title of the OTP entry in Authenticator

      Returns:
         provisioning URI

   verify(otp: str, counter: int) -> bool

      Verifies the OTP passed in against the current counter OTP.

      Parameters:
         * **otp** -- the OTP to check against

         * **counter** -- the OTP HMAC counter

pyotp.utils.build_uri(secret: str, name: str, initial_count: int | None = None, issuer: str | None = None, algorithm: str | None = None, digits: int | None = None, period: int | None = None, **kwargs) -> str

   Returns the provisioning URI for the OTP; works for either TOTP or
   HOTP.

   This can then be encoded in a QR Code and used to provision the
   Google Authenticator app.

   For module-internal use.

   See also:
      https://github.com/google/google-authenticator/wiki/Key-Uri-
      Format

   Parameters:
      * **secret** -- the hotp/totp secret used to generate the URI

      * **name** -- name of the account

      * **initial_count** -- starting counter value, defaults to None.
        If none, the OTP type will be assumed as TOTP.

      * **issuer** -- the name of the OTP issuer; this will be the
        organization title of the OTP entry in Authenticator

      * **algorithm** -- the algorithm used in the OTP generation.

      * **digits** -- the length of the OTP generated code.

      * **period** -- the number of seconds the OTP generator is set
        to expire every code.

      * **kwargs** -- other query string parameters to include in the
        URI

   Returns:
      provisioning uri

pyotp.utils.strings_equal(s1: str, s2: str) -> bool

   Timing-attack resistant string comparison.

   Normal comparison using == will short-circuit on the first
   mismatching character. This avoids that by scanning the whole
   string, though we still reveal to a timing attack whether the
   strings are the same length.

class pyotp.contrib.steam.Steam(s: str, name: str | None = None, issuer: str | None = None, interval: int = 30, digits: int = 5)

   Steam's custom TOTP. Subclass of *pyotp.totp.TOTP*.

   generate_otp(input: int) -> str

      Parameters:
         **input** -- the HMAC counter value to use as the OTP input.
         Usually either the counter, or the computed integer based on
         the Unix timestamp


Change log
**********

* Release Notes

* Changes for v2.10.0 (2026-06-13)

* Changes for v2.9.0 (2023-07-27)

* Changes for v2.8.0 (2022-12-13)

* Changes for v2.7.0 (2022-09-11)

* Changes for v2.6.0 (2021-02-04)

* Changes for v2.5.1 (2021-01-29)

* Changes for v2.5.0 (2021-01-29)

* Changes for v2.4.1 (2020-10-16)

* Changes for v2.4.0 (2020-07-29)

* Changes for v2.3.0 (2019-07-26)

* Changes for v2.2.8 (2019-07-26)

* Changes for v2.2.7 (2018-11-05)

* Changes for v2.2.6 (2017-06-10)

* Changes for v2.2.5 (2017-06-03)

* Changes for v2.2.4 (2017-01-04)

* Changes for v2.2.3 (2017-01-04)

* Changes for v2.2.2 (2017-01-04)

* Changes for v2.2.1 (2016-08-30)

* Changes for v2.2.0 (2016-08-30)

  * Version 2.1.0 (2016-05-02)

  * Version 2.0.1 (2015-09-28)

  * Version 2.0.0 (2015-08-22)

  * Version 1.4.2 (2015-07-21)

  * Version 1.3.1 (2012-02-29)
