Skip to main content
Skyvern supports three 2FA methods for automated logins. Authenticator App (TOTP) is fully automatic: Skyvern generates codes locally. Email and Text Message require you to push codes via the API. All three are configured on the password credential itself.

Authenticator App (TOTP)

The preferred method. Skyvern generates valid 6-digit codes on demand during login flows with no delay and no manual steps.

How it works

  1. The Login block enters the username and password
  2. The site prompts for a 2FA code
  3. Skyvern generates a fresh TOTP code from the stored secret key
  4. The code is entered automatically and login completes

Setting it up

When creating a password credential, include the TOTP secret key:
from skyvern import Skyvern

skyvern = Skyvern(api_key="YOUR_API_KEY")

credential = await skyvern.create_credential(
    name="Salesforce with 2FA",
    credential_type="password",
    credential={
        "username": "[email protected]",
        "password": "securepassword123",
        "totp": "JBSWY3DPEHPK3PXP",  # Your TOTP secret key
        "totp_type": "authenticator"
    }
)
The secret key is the base32-encoded string behind the QR code you’d normally scan in an authenticator app. You can find it in a few places:
  • Bitwarden: Edit the login → TOTP field → copy the key
  • 1Password: Edit the login → One-Time Password → copy the secret
  • LastPass: Edit the login → Advanced Settings → copy the TOTP secret
  • Site settings: Many sites show a “Can’t scan?” link during 2FA setup that reveals the text key
If you only have a QR code, decode it to extract the secret= parameter from the otpauth://totp/...?secret=BASE32KEY URI.

Email and Text Message codes

When a site sends 2FA codes via email or SMS, someone (or something) needs to deliver the code to Skyvern before the login can complete.

How it works

  1. The Login block enters the username and password
  2. The site sends a 2FA code to the configured email or phone number
  3. You push the code to Skyvern via the API
  4. Skyvern enters the code and completes the login

Setting it up

When creating a password credential, specify totp_type as "email" or "text" and include the totp_identifier:
credential = await skyvern.create_credential(
    name="GitHub with Email 2FA",
    credential_type="password",
    credential={
        "username": "[email protected]",
        "password": "securepassword123",
        "totp_type": "email",
        "totp_identifier": "[email protected]"
    }
)

Pushing codes to Skyvern

Once a workflow is running and waiting for a 2FA code, you need to deliver it.

Via the API

For production, automate code delivery. Set up a forwarding rule that sends 2FA emails or texts to a script, and the script pushes the code to Skyvern:
from skyvern import Skyvern

skyvern = Skyvern(api_key="YOUR_API_KEY")

await skyvern.send_totp_code(
    totp_identifier="[email protected]",
    content="Your verification code is 847291",
    source="email_forwarder",
)
Response:
{
  "totp_code_id": "tc_abc123",
  "totp_identifier": "[email protected]",
  "code": "847291",
  "source": "email_forwarder",
  "created_at": "2025-01-15T10:30:00Z",
  "expired_at": null,
  "otp_type": "totp"
}
The source field is a free-text label for your own tracking (e.g., "email_forwarder", "twilio_webhook").

Parsing the code automatically

Skyvern automatically extracts verification codes from email/SMS content. You can pass:
  • Just the code: "847291"
  • The full email/SMS body: "Your verification code is 847291. This code expires in 10 minutes."
Skyvern will extract the numeric code automatically.

Linking codes to specific runs

To link a code to a specific run, pass workflow_run_id, workflow_id, or task_id:
await skyvern.send_totp_code(
    totp_identifier="[email protected]",
    content="Your verification code is 847291",
    source="email_forwarder",
    workflow_run_id="wr_1234567890",
)
This turns email-based 2FA into something nearly as automated as an authenticator app. The main difference is latency while the email arrives and gets forwarded.

Viewing past codes

Retrieve recent TOTP codes for your organization:
codes = await skyvern.get_totp_codes(
    totp_identifier="[email protected]",
    limit=50
)

for code in codes:
    print(f"Code: {code.code}, Source: {code.source}, Created: {code.created_at}")
Response:
[
  {
    "totp_code_id": "tc_abc123",
    "totp_identifier": "[email protected]",
    "code": "847291",
    "source": "email_forwarder",
    "created_at": "2025-01-15T10:30:00Z",
    "expired_at": null,
    "otp_type": "totp",
    "workflow_run_id": "wr_1234567890"
  }
]

Query parameters

ParameterTypeDescription
totp_identifierstringFilter by email or phone number
workflow_run_idstringFilter by workflow run ID
otp_type"totp" or "magic_link"Filter by OTP type
limitintegerMaximum number of codes (1-200, default 50)
Use this for auditing and debugging: confirming that a code was received and delivered to the right run.

OTP Types

Skyvern supports two OTP types:
TypeDescription
"totp"Time-based One-Time Password (numeric code)
"magic_link"Magic link URLs sent via email
By default, Skyvern auto-detects the type based on the content. For magic links, pass the full URL in the content field.

Password Credentials

Create credentials with 2FA methods attached

Credentials Overview

Security model, quick start, and all credential types

Build docs developers (and LLMs) love