Sunday, September 6, 2026

How to Generate an OTP Using Python: A Simple Beginner-Friendly Guide

 

How to Generate an OTP Using Python: A Simple Beginner-Friendly Guide

One-Time Passwords, commonly called OTPs, have become a familiar part of modern digital life. Whether you are logging into an account, confirming a transaction, resetting a password, or verifying a phone number, an OTP provides an additional layer of security.

Python makes it surprisingly easy to create a basic OTP generator. In this tutorial, we will build one from scratch and understand how the code works.

What Is an OTP?

An OTP is a temporary password that is generally valid for only one authentication attempt or for a short period.

A typical OTP might look like:

583214

Unlike a permanent password, an OTP is designed to be short-lived. This makes it useful for identity verification and multi-factor authentication.

There are several types of OTPs, including:

  • Numeric OTPs — such as 583214
  • Alphanumeric OTPs — such as A7K92P
  • Time-based OTPs (TOTP) — codes that change automatically after a fixed interval
  • Event-based OTPs (HOTP) — codes generated based on an event or counter

For learning purposes, let's start with a simple six-digit numeric OTP.

Why Use Python for OTP Generation?

Python includes a number of useful modules for generating random values.

For security-sensitive applications, the secrets module is particularly important. Unlike ordinary pseudo-random functions intended for simulations or general programming, secrets is designed for generating values suitable for security-related purposes.

We can therefore create an OTP generator with only a few lines of code.

Method 1: Generate a Six-Digit OTP

Here is a simple example:

import secrets

otp = ''.join(str(secrets.randbelow(10)) for _ in range(6))

print("Your OTP is:", otp)

Example output

Your OTP is: 583214

Every time you run the program, a different OTP should normally be produced.

Understanding the Code

Let's break it down.

Import the secrets module

import secrets

The secrets module provides functions for generating cryptographically stronger random values.

Generate a random digit

secrets.randbelow(10)

This produces a random integer from 0 through 9.

For example:

7

Generate six digits

for _ in range(6)

This repeats the operation six times.

Convert the digits to strings

str(secrets.randbelow(10))

The generated number is converted into text so that the digits can be joined together.

Join everything together

''.join(...)

This combines the six individual digits into a single OTP.

Method 2: Using secrets.choice()

Another clean approach is to create a collection of digits and randomly select from it.

import secrets
import string

digits = string.digits

otp = ''.join(secrets.choice(digits) for _ in range(6))

print("Generated OTP:", otp)

Here, string.digits contains:

0123456789

The program randomly selects six digits from that collection.

Creating an OTP Generator Function

Instead of writing the code repeatedly, we can put it inside a function.

import secrets

def generate_otp(length=6):
    return ''.join(str(secrets.randbelow(10)) for _ in range(length))

otp = generate_otp()

print("Your OTP is:", otp)

The advantage is that we can easily change the OTP length.

For example:

print(generate_otp(4))
print(generate_otp(6))
print(generate_otp(8))

Possible output:

4821
735914
19384726

Building a Simple OTP Verification System

Generating an OTP is only one part of authentication. We also need to verify whether the user entered the correct code.

Here's a simple example:

import secrets

def generate_otp():
    return ''.join(str(secrets.randbelow(10)) for _ in range(6))

otp = generate_otp()

print("OTP generated successfully.")

user_input = input("Enter the OTP: ")

if user_input == otp:
    print("OTP verified successfully!")
else:
    print("Invalid OTP.")

The program generates an OTP and asks the user to enter it.

If the entered value matches the generated value, verification succeeds.

Adding an Expiration Time

Real-world OTP systems generally don't allow a code to remain valid forever.

We can demonstrate expiration using Python's time module.

import secrets
import time

otp = ''.join(str(secrets.randbelow(10)) for _ in range(6))

created_at = time.time()

print("Your OTP is:", otp)

user_input = input("Enter OTP: ")

if time.time() - created_at > 30:
    print("OTP expired.")
elif user_input == otp:
    print("OTP verified successfully!")
else:
    print("Invalid OTP.")

In this example, the OTP is considered valid for 30 seconds.

This is only a demonstration. Production authentication systems require additional safeguards.

Creating a Complete Mini OTP Program

We can combine generation, expiration, and verification into a small application.

import secrets
import time

def generate_otp():
    return ''.join(str(secrets.randbelow(10)) for _ in range(6))

otp = generate_otp()
created_at = time.time()

print("OTP generated successfully.")
print("For demonstration:", otp)

user_input = input("Enter your OTP: ")

if time.time() - created_at > 30:
    print("The OTP has expired.")
elif secrets.compare_digest(user_input, otp):
    print("OTP verification successful.")
else:
    print("Incorrect OTP.")

secrets.compare_digest() can be useful when comparing security-sensitive strings because it is designed to reduce timing-attack risks.

Generating an Alphanumeric OTP

Sometimes an OTP doesn't have to contain only numbers.

We can create an alphanumeric code like:

K7P2XA

Example:

import secrets
import string

characters = string.ascii_uppercase + string.digits

otp = ''.join(secrets.choice(characters) for _ in range(6))

print("Your OTP is:", otp)

Possible output:

Your OTP is: Q8M2KP

random vs secrets in Python

Beginners often encounter the random module and may wonder why we use secrets for OTPs.

For example:

import random

otp = random.randint(100000, 999999)

This can be useful for demonstrations and non-security-related applications, but authentication codes should generally use a security-oriented random source.

For OTP generation, prefer:

import secrets

rather than relying on:

import random

The distinction is important because security systems need unpredictable values.

Important Security Considerations

A simple Python OTP generator is excellent for learning, but a real authentication system needs considerably more protection.

1. Don't print OTPs in production

The examples above print the OTP to the terminal for demonstration.

A real application would normally deliver the OTP through an appropriate verification channel instead.

2. Set an expiration time

An OTP should normally have a limited lifetime.

3. Limit verification attempts

An attacker should not be able to try thousands of codes against an account.

4. Avoid storing OTPs unnecessarily

If an application needs to store OTP-related information, it should use an appropriate secure design rather than keeping sensitive values in plain text indefinitely.

5. Protect the delivery mechanism

Sending an OTP through an insecure channel can undermine the security of the entire system.

6. Don't use predictable codes

Avoid algorithms such as:

otp = "123456"

or codes derived from predictable information such as birthdays.

Where Can Python OTPs Be Used?

OTP systems can be incorporated into many applications, including:

  • User registration
  • Login verification
  • Password recovery
  • Email verification
  • Mobile-number verification
  • Transaction confirmation
  • Account recovery
  • Multi-factor authentication
  • Temporary access codes

Python frameworks such as Django, Flask, and FastAPI can be used to integrate OTP functionality into larger web applications.

Final Thoughts

Generating an OTP with Python is a small project that teaches several useful programming concepts, including functions, loops, random generation, string manipulation, user input, and time-based validation.

For a basic project, Python's secrets module provides a straightforward way to generate unpredictable OTP values:

import secrets

otp = ''.join(str(secrets.randbelow(10)) for _ in range(6))

print(otp)

The important lesson is that generating an OTP and building a secure OTP authentication system are two different things. A production application also needs expiration, rate limiting, secure storage practices, protected delivery, monitoring, and careful handling of authentication attempts.

For beginners, however, an OTP generator is an excellent Python project—and a natural stepping stone toward building more sophisticated authentication systems.