The getpass module provides secure password input—characters aren't echoed to the terminal. Simple but essential for CLI tools.

Basic Password Input

import getpass
 
password = getpass.getpass()
# Prompts: "Password: " (input hidden)
 
# Custom prompt
password = getpass.getpass("Enter your secret: ")

The input isn't echoed—no characters appear as you type.

Get Current Username

import getpass
 
username = getpass.getuser()
print(f"Current user: {username}")
# Gets from LOGNAME, USER, LNAME, USERNAME env vars
# Falls back to pwd module on Unix

Practical Examples

Login Prompt

import getpass
 
def login():
    username = input("Username: ")
    password = getpass.getpass("Password: ")
    
    if authenticate(username, password):
        print("Login successful")
    else:
        print("Invalid credentials")
 
def authenticate(username, password):
    # Your auth logic here
    return username == "admin" and password == "secret"

Database Connection

import getpass
 
def connect_db():
    host = input("Host [localhost]: ") or "localhost"
    user = input(f"User [{getpass.getuser()}]: ") or getpass.getuser()
    password = getpass.getpass()
    database = input("Database: ")
    
    return {
        'host': host,
        'user': user,
        'password': password,
        'database': database,
    }

API Key Input

import getpass
import os
 
def get_api_key():
    # Check environment first
    key = os.environ.get('API_KEY')
    if key:
        return key
    
    # Prompt securely
    return getpass.getpass("API Key: ")

Sudo-Style Confirmation

import getpass
 
def confirm_action(action: str) -> bool:
    print(f"This will {action}")
    password = getpass.getpass(f"[sudo] password for {getpass.getuser()}: ")
    return verify_password(password)

Handling Non-TTY Input

When stdin isn't a terminal (piped input), getpass warns and may fail:

import getpass
import sys
 
def safe_getpass(prompt="Password: "):
    if sys.stdin.isatty():
        return getpass.getpass(prompt)
    else:
        # Fallback for non-interactive
        print(prompt, end='', file=sys.stderr)
        return sys.stdin.readline().rstrip('\n')

With Environment Variables

import getpass
import os
 
def get_credentials():
    """Get credentials from env or prompt."""
    username = os.environ.get('APP_USER')
    password = os.environ.get('APP_PASSWORD')
    
    if not username:
        username = input("Username: ")
    
    if not password:
        password = getpass.getpass()
    
    return username, password

Masked Input Alternative

getpass shows nothing. For asterisks, you need more code:

import sys
 
def getpass_masked(prompt="Password: "):
    """Show asterisks as user types."""
    if sys.platform == 'win32':
        import msvcrt
        print(prompt, end='', flush=True)
        chars = []
        while True:
            char = msvcrt.getwch()
            if char in ('\r', '\n'):
                print()
                return ''.join(chars)
            elif char == '\x08':  # Backspace
                if chars:
                    chars.pop()
                    print('\b \b', end='', flush=True)
            else:
                chars.append(char)
                print('*', end='', flush=True)
    else:
        # Unix: use getpass (no easy masking)
        import getpass
        return getpass.getpass(prompt)

Security Considerations

import getpass
 
# Password is still in memory as a string
password = getpass.getpass()
 
# Clear after use (helps, but not guaranteed)
# Python strings are immutable, so this creates a new object
password = None
 
# For high-security apps, consider:
# - Using SecureString equivalents if available
# - Hashing immediately after input
# - Using memory-safe languages for auth handling

Testing Code with getpass

import getpass
from unittest.mock import patch
 
def login(username, password):
    return username == "admin" and password == "secret"
 
def main():
    username = input("Username: ")
    password = getpass.getpass()
    return login(username, password)
 
# Test
def test_login():
    with patch('builtins.input', return_value='admin'):
        with patch('getpass.getpass', return_value='secret'):
            assert main() == True

Quick Reference

import getpass
 
# Secure password input (no echo)
password = getpass.getpass()
password = getpass.getpass("Custom prompt: ")
 
# Get current username
username = getpass.getuser()
FunctionPurpose
getpass()Read password without echo
getuser()Get current username

That's it—two functions. getpass does one thing well: hide password input. Use it for any CLI that needs credentials.

React to this post: