pyauthenticator
TOTP authentication for Python, the command line, and automation.
pyauthenticator provides a lightweight way to manage and generate time-based one-time passwords (TOTP) from scripts, Python applications, command-line workflows, and MCP clients.
It is particularly useful when a service requires two-factor authentication but does not provide application-specific passwords, API tokens, or another authentication mechanism suitable for automation.
Once an account has been imported from its authenticator QR code, generating a code is as simple as:
pyauthenticator github
or from Python:
from pyauthenticator import get_two_factor_code
code = get_two_factor_code("github")
Why pyauthenticator?
Libraries such as PyOTP provide the underlying HOTP/TOTP algorithms for Python applications. pyauthenticator builds on PyOTP and focuses instead on managing and consuming TOTP credentials for automation.
| PyOTP | pyauthenticator | |
|---|---|---|
| Generate TOTP/HOTP codes | ✅ | ✅ |
| Verify OTP codes | ✅ | — |
Parse otpauth:// URIs |
✅ | ✅ |
| Manage named accounts | — | ✅ |
| Import authenticator QR codes | — | ✅ |
| Persistent local credential store | — | ✅ |
| Command-line interface | — | ✅ |
| High-level Python interface | — | ✅ |
| MCP server | — | ✅ |
| Primary use case | Implement OTP authentication | Use existing TOTP credentials in automation |
In short:
- Use PyOTP when implementing OTP authentication inside an application.
- Use pyauthenticator when you already have TOTP credentials and want to access them conveniently from Python, the shell, SSH automation, or other tools.
Installation
Install pyauthenticator from conda-forge:
conda install -c conda-forge pyauthenticator
or from PyPI:
pip install pyauthenticator
Quick start
Add an account
Save the QR code normally shown when configuring an authenticator application.
For example, if the QR code is stored as:
~/Desktop/github-qrcode.png
add it as the service github:
pyauthenticator github --add ~/Desktop/github-qrcode.png
pyauthenticator extracts the otpauth:// credential from the QR code and stores it locally.
Generate a TOTP code
After adding the service:
pyauthenticator github
returns the current authentication code:
087078
pyauthenticator works with services using standard TOTP authentication, not only Google accounts.
Command-line interface
Display the available options with:
pyauthenticator --help
Example output:
usage: pyauthenticator [-h] [-qr] [-a ADD] service
positional arguments:
service Service to generate optauth code for. Currently no
service is defined in the ~/.pyauthenticator config file.
options:
-h, --help show this help message and exit
-qr, --qrcode Generate qrcode as <service.png> file.
-a ADD, --add ADD Add service by providing the <qrcode.png> file as
additional argument.
Import an account
For example:
pyauthenticator google --add ~/Desktop/google-qrcode.png
Generate a code
pyauthenticator google
Export a QR code
The QR code associated with a configured service can be generated with:
pyauthenticator google --qrcode
Service-name suggestions
If a service name is mistyped, pyauthenticator lists the configured services and suggests alternatives:
pyauthenticator googel
For example:
The service "googel" does not exist.
The config file ~/.pyauthenticator contains the following services:
* google
Choose one of these or add a new service using:
pyauthenticator --add <qr-code.png> <servicename>
Using pyauthenticator for automation
The command-line interface makes TOTP codes directly available to shell scripts and other programs.
For example:
TOKEN="$(pyauthenticator github)"
The resulting value can then be passed to another process which requires a TOTP code.
This makes pyauthenticator useful for workflows such as:
- shell scripts,
- SSH authentication helpers,
- automated command-line applications,
- Python workflows,
- developer tools,
- MCP-compatible agents.
Whenever possible, dedicated API tokens, application passwords, SSH keys, OAuth credentials, or other machine-oriented authentication mechanisms should be preferred. pyauthenticator is intended for situations where a service requires TOTP authentication and no more suitable automation interface is available.
Python interface
The same functionality is available through Python:
from pyauthenticator import get_two_factor_code
code = get_two_factor_code("github")
This allows existing Python applications and workflows to access services protected by TOTP authentication without reimplementing credential loading or OTP generation.
Configuration
Configured services are stored in:
~/.pyauthenticator
The configuration uses JSON. A configured service contains the otpauth:// URI extracted from the corresponding QR code.
For example:
{
"google": "otpauth://totp/Google:<username>?secret=<secret>&issuer=Google"
}
The URI contains the TOTP secret required to generate authentication codes.
Security considerations
The TOTP secret stored by pyauthenticator is an authentication credential. Anyone who can obtain this secret can generate the same one-time passwords.
The local ~/.pyauthenticator configuration should therefore be treated like other sensitive credential files.
Using TOTP from an automated process also changes the traditional security model of two-factor authentication: the password and second-factor secret may ultimately become accessible from the same machine.
For automated access, prefer mechanisms explicitly designed for machine authentication whenever the target service provides them, such as:
- API tokens,
- application-specific passwords,
- SSH keys,
- OAuth credentials,
- service accounts.
pyauthenticator is intended primarily for services where TOTP authentication is required and no suitable machine-oriented alternative exists.
Because automating two-factor authentication can conflict with the security policies of the organization operating the target service — for example institutional computing centres — confirm that this use is permitted before automating TOTP entry with pyauthenticator.
MCP server
pyauthenticator also provides an MCP server for MCP-compatible hosts on Python 3.10+.
Install the optional MCP dependency with:
pip install "pyauthenticator[mcp]"
The server is exposed through:
pyauthenticator-mcp
The MCP server uses the same ~/.pyauthenticator configuration as the command-line and Python interfaces. Services added through one interface are therefore immediately available through the others.
Example MCP configuration
An MCP-compatible host can launch the server using a configuration such as:
{
"mcpServers": {
"pyauthenticator": {
"command": "/absolute/path/to/pyauthenticator-mcp"
}
}
}
Using an absolute path is recommended because desktop applications commonly start MCP servers without loading the environment configuration of an interactive shell.
If pyauthenticator-mcp is installed inside a conda environment or virtual environment, find the executable with:
which pyauthenticator-mcp
and use the resulting path in the MCP configuration.
Claude Desktop configuration
Claude Desktop stores its MCP configuration in claude_desktop_config.json.
Typical locations are:
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - Windows:
%APPDATA%\Claude\claude_desktop_config.json - Linux:
~/.config/Claude/claude_desktop_config.json
In Claude Desktop, the configuration can also be accessed through Settings → Developer → Edit Config.
Only add or modify the mcpServers entry needed for pyauthenticator; leave unrelated settings unchanged.
For example:
{
"mcpServers": {
"pyauthenticator": {
"command": "/Users/<you>/mambaforge/bin/pyauthenticator-mcp"
}
},
"preferences": {
"...": "..."
}
}
Available MCP tools
| Tool | Arguments | Description |
|---|---|---|
get_code |
service: str |
Generate a two-factor authentication code for a configured service. |
list_services |
– | List configured service names. |
add_service |
service: str, qrcode_path: Optional[str], qrcode_base64: Optional[str] |
Add a service from a QR-code file or base64-encoded PNG. |
remove_service |
service: str |
Remove a configured service. |
get_qrcode |
service: str |
Return the QR code for a configured service as an MCP image. |
get_code, remove_service, and get_qrcode report the currently configured services when the requested service does not exist, mirroring the command-line behavior.
Use cases
pyauthenticator is intended as a small bridge between TOTP authentication and automation.
Typical applications include:
Command-line workflows
pyauthenticator myservice
Shell scripts
OTP="$(pyauthenticator myservice)"
See Using TOTP codes in shell scripts and CLI workflows for more examples.
Python applications
from pyauthenticator import get_two_factor_code
otp = get_two_factor_code("myservice")
See Generating TOTP codes from Python for more examples.
SSH and remote-system automation
pyauthenticator can be combined with SSH_ASKPASS when an SSH login requires a password followed by a TOTP code.
See Automating SSH logins that require a password and a TOTP code for a complete, working example.
ssh invokes the program configured as SSH_ASKPASS whenever it needs to request input, passing the prompt text as an argument. Setting SSH_ASKPASS_REQUIRE=force makes ssh use this program even when run from an interactive terminal.
For example, ~/.bashrc or ~/.zshrc could contain:
export SSH_ASKPASS="$HOME/.ssh/askpass-helper.sh"
export SSH_ASKPASS_REQUIRE=force
and ~/.ssh/askpass-helper.sh (marked executable with chmod +x) could dispatch based on the prompt text:
#!/usr/bin/env bash
set -euo pipefail
PROMPT="${1:-}"
case "$PROMPT" in
*"'s password:"*)
# Retrieve the password from a secure credential store,
# e.g. the macOS keychain via `security find-generic-password`.
echo "<password>"
;;
*"Your OTP:"*)
# Generate the current TOTP code for the "myservice" account.
exec pyauthenticator myservice
;;
*)
echo "Unexpected SSH prompt: $PROMPT" >&2
exit 1
;;
esac
The exact prompt text (Your OTP: in this example) depends on the SSH server and PAM configuration of the target system and may need to be adjusted.
Note: Automating two-factor prompts like this removes the human-in-the-loop step that two-factor authentication is meant to provide, and some computing centres and organizations explicitly prohibit it. Only use this approach when it is consistent with the security policies of the systems and organizations you connect to — check with the relevant administrators first. The same caution applies to any automated use of
pyauthenticatorbeyond this specific example.
Agent and MCP workflows
The optional MCP server exposes configured TOTP credentials to MCP-compatible applications while retaining the same local credential store used by the CLI and Python interfaces.
See Giving an MCP agent (e.g. Claude) access to TOTP codes for a complete setup and example.
Support
Questions, bug reports, feature requests, and integration examples are welcome through the GitHub issue tracker.
Contributions that improve automation workflows, integrations, platform support, documentation, or credential handling are particularly welcome.
License
pyauthenticator is licensed under the BSD-3-Clause license.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pyauthenticator-0.4.1.tar.gz.
File metadata
- Download URL: pyauthenticator-0.4.1.tar.gz
- Upload date:
- Size: 10.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
290801a893c68dfa55b71f515101100eb222ebe69b344bbbfecf7e6d7343d824
|
|
| MD5 |
6ccd46dd670e6f4fb207aa72eb65613d
|
|
| BLAKE2b-256 |
ab194dbdcb93c20749101d131924a2ab65ed514e060f919b825083ea1a602936
|
Provenance
The following attestation bundles were made for pyauthenticator-0.4.1.tar.gz:
Publisher:
deploy.yml on jan-janssen/pyauthenticator
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pyauthenticator-0.4.1.tar.gz -
Subject digest:
290801a893c68dfa55b71f515101100eb222ebe69b344bbbfecf7e6d7343d824 - Sigstore transparency entry: 2409787481
- Sigstore integration time:
-
Permalink:
jan-janssen/pyauthenticator@ed8a808ff93a0aa105fdfafd4aee981dca80d35f -
Branch / Tag:
refs/tags/pyauthenticator-0.4.1 - Owner: https://github.com/jan-janssen
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
deploy.yml@ed8a808ff93a0aa105fdfafd4aee981dca80d35f -
Trigger Event:
push
-
Statement type:
File details
Details for the file pyauthenticator-0.4.1-py3-none-any.whl.
File metadata
- Download URL: pyauthenticator-0.4.1-py3-none-any.whl
- Upload date:
- Size: 13.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
997a63e336f02e1b9c812aaca3f0bd2d2d4d4c061ed253c94d2ec5bfa0e80769
|
|
| MD5 |
7976130d33f4a547bfa16b2b087ff6af
|
|
| BLAKE2b-256 |
1817edb98c40ba3b9ce802ddc16854f232194f2af333efe19debb09a71eb9625
|
Provenance
The following attestation bundles were made for pyauthenticator-0.4.1-py3-none-any.whl:
Publisher:
deploy.yml on jan-janssen/pyauthenticator
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pyauthenticator-0.4.1-py3-none-any.whl -
Subject digest:
997a63e336f02e1b9c812aaca3f0bd2d2d4d4c061ed253c94d2ec5bfa0e80769 - Sigstore transparency entry: 2409787519
- Sigstore integration time:
-
Permalink:
jan-janssen/pyauthenticator@ed8a808ff93a0aa105fdfafd4aee981dca80d35f -
Branch / Tag:
refs/tags/pyauthenticator-0.4.1 - Owner: https://github.com/jan-janssen
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
deploy.yml@ed8a808ff93a0aa105fdfafd4aee981dca80d35f -
Trigger Event:
push
-
Statement type: