Skip to main content
Many websites require two-factor authentication (2FA) during login. Skyvern supports multiple 2FA methods to handle these flows automatically.

Choose your method

Select the method that matches how you receive verification codes:
ScenarioRecommended Method
You have the TOTP secret keyStore TOTP secret — Skyvern generates codes
Codes sent to email/SMS you can forwardPush codes to Skyvern
Codes sent to a system you controlSkyvern pulls from your endpoint
Passwordless/magic link authMagic links
Using Bitwarden with TOTPPassword manager integration

Method 1: Store TOTP secret

Best for: Sites where you have access to the TOTP secret (the setup QR code or manual key). When you enable 2FA on a website, you’re typically shown a QR code or a secret key. Store this secret with your credential, and Skyvern generates valid codes automatically.
import os
from skyvern import Skyvern

client = Skyvern(api_key=os.getenv("SKYVERN_API_KEY"))

credential = await client.create_credential(
    name="Acme Portal Login",
    credential_type="password",
    credential={
        "username": "user@example.com",
        "password": "secure_password",
        "totp": "JBSWY3DPEHPK3PXP",  # Base32 secret from QR code
        "totp_type": "authenticator",
    },
)

TOTP types

TypeDescription
authenticatorStandard TOTP codes (Google Authenticator, Authy, etc.)
emailCodes sent via email that you’ll push to Skyvern
textCodes sent via SMS that you’ll push to Skyvern
Skyvern generates TOTP codes using standard 30-second windows. If the current code has less than 20 seconds remaining, Skyvern automatically uses the next code to ensure successful entry.

Finding your TOTP secret

Most sites show the secret when you set up 2FA:
  1. Go to your account’s security settings
  2. Click “Set up authenticator app”
  3. Look for “Can’t scan the QR code?” or “Manual entry”
  4. Copy the secret key (usually Base32 format like JBSWY3DPEHPK3PXP)
If you’ve already set up 2FA and don’t have the secret, you may need to disable and re-enable 2FA to see the secret again. Contact support@skyvern.com for help.

Method 2: Push codes to Skyvern

Best for: Codes sent to email or SMS that you can programmatically forward. When your automation encounters a 2FA prompt, Skyvern polls for codes that you push via API. Your email or SMS forwarding system sends codes to Skyvern as they arrive.

Step 1: Set up code forwarding

Configure your email or SMS to forward verification codes to Skyvern. Common approaches:
  • Email: Gmail filter + Zapier webhook
  • SMS: Twilio webhook to your server
  • Email: AWS SES + Lambda function
This setup requires a Zapier Pro plan account.
1

Create a Zapier Zap

  1. Go to zapier.com and create a new Zap
  2. In the newly created Zap draft, click the “Trigger” button
  3. Click Email by Zapier
  4. In the Email “Setup”, pick New Inbound Email in the Trigger event selection. Click Continue
  5. In Email “Configure”, create an email address which will be used to forward emails for TOTP codes. Click Continue
  6. Click the “Action” button and add Webhooks by Zapier
  7. In the Setup, choose POST under the Action event selection. Click Continue
  8. In the “Configure”, set up these fields to make a POST request to Skyvern’s TOTP API:
    • URL: https://api.skyvern.com/v1/credentials/totp
    • Payload Type: json
    • Data:
      • totp_identifier: choose Raw To Email after clicking the ”+” sign
      • content: choose Body Plain after clicking the ”+” sign
      • source: email
    • Headers:
      • x-api-key: your Skyvern API key
  9. Click Continue
2

Add forwarding email and create a filter in Gmail

Go to Gmail Settings → Forwarding and POP/IMAP → click Add a forwarding address → enter the Zapier email address you created. Complete any verification steps.Then go to Filters and Blocked Addresses. Click Create a new filter and set up a filtering rule for your TOTP (2FA/MFA) emails. Click Create filter, check Forward it to, pick the Zapier email address, and update the filter.
Gmail forwarding filter
3

Test it end to end

Forward any previous TOTP email to the Zapier email address you created.In Zapier, under the “Test” of the Webhooks action, send a request to test it out. If successful, you should see a “A request was sent to Webhooks by Zapier” message.
Use a virtual phone number service like Twilio or Plivo to receive SMS codes and forward them to Skyvern.
1

Set up a Twilio phone number

Create a Twilio account and provision a phone number. This number will receive the SMS verification codes.
2

Create a Twilio Function to forward codes

In your Twilio console, create a new Function that forwards incoming SMS to Skyvern’s TOTP API:
// Twilio Function
exports.handler = async function(context, event, callback) {
  const axios = require('axios');

  await axios.post('https://api.skyvern.com/v1/credentials/totp', {
    totp_identifier: event.To,  // Your Twilio phone number
    content: event.Body,
    source: 'phone'
  }, {
    headers: {
      'x-api-key': context.SKYVERN_API_KEY,
      'Content-Type': 'application/json'
    }
  });

  return callback(null, new Twilio.Response());
};
Add your SKYVERN_API_KEY as an environment variable in the Twilio Function configuration.
3

Configure the webhook

In your Twilio phone number settings, set the A Message Comes In webhook to point to your Twilio Function URL.
4

Test it

Send a test SMS to your Twilio number and verify the code appears in Skyvern:
curl -X GET "https://api.skyvern.com/v1/credentials/totp?totp_identifier=YOUR_TWILIO_NUMBER" \
  -H "x-api-key: $SKYVERN_API_KEY"

Step 2: Start the run with a TOTP identifier

When running your login, include a totp_identifier that matches what you’ll use when pushing codes:
result = await client.login(
    credential_type="skyvern",
    url="https://portal.example.com/login",
    credential_id="cred_xyz789",
    totp_identifier="user@example.com",  # Must match when pushing code
)

Step 3: Push the code when received

When the verification code arrives, push it to Skyvern:
await client.send_totp_code(
    totp_identifier="user@example.com",
    content="Your verification code is 123456",  # Full email/SMS body
    source="email",
)
If content is longer than 10 characters, Skyvern’s AI extracts the verification code automatically. You can send the full email or SMS body without parsing it yourself.

Method 3: Skyvern pulls from your endpoint

Best for: Environments where you control the system receiving 2FA codes and can expose them via an HTTP endpoint. Instead of pushing codes to Skyvern, you implement an endpoint that Skyvern polls until a code is available.

Step 1: Implement the endpoint

Your endpoint must accept POST requests and return the verification code: Request from Skyvern:
POST https://your-server.com/totp-webhook
x-skyvern-signature: <hmac-sha256-signature>
Content-Type: application/json

{
  "task_id": "tsk_123456"
}
Expected response:
{
  "task_id": "tsk_123456",
  "verification_code": "123456"
}

Step 2: Verify request signatures

Skyvern signs all requests using HMAC-SHA256 with your API key. Verify the signature to ensure requests are authentic:
import hmac
import hashlib

def verify_skyvern_request(request, api_key: str) -> bool:
    signature = request.headers.get("x-skyvern-signature")
    payload = request.body  # bytes

    expected = hmac.new(
        api_key.encode("utf-8"),
        msg=payload,
        digestmod=hashlib.sha256
    ).hexdigest()

    return hmac.compare_digest(signature, expected)

Step 3: Configure the login

Pass totp_url when running your login:
result = await client.login(
    credential_type="skyvern",
    url="https://portal.example.com/login",
    credential_id="cred_xyz789",
    totp_url="https://your-server.com/totp-webhook",
)
Skyvern polls your endpoint every 10 seconds until a code is returned or the timeout is reached.
Best for: Passwordless authentication systems that send one-time login links. When a site uses magic links instead of passwords, push the link to Skyvern:
await client.send_totp_code(
    totp_identifier="user@example.com",
    content="https://portal.example.com/login?token=abc123xyz",
    source="email",
)
Skyvern automatically detects URLs and classifies them as magic links. The automation will navigate to the link to complete authentication.
For magic link flows, structure your workflow in two parts:
  1. Trigger the magic link — Navigate to login and enter email
  2. Complete login — Use the magic link as the starting URL for the next step

Password manager TOTP

If you store TOTP secrets in Bitwarden or 1Password, Skyvern can retrieve both the password and TOTP code in a single request.

Bitwarden

Store your TOTP secret in Bitwarden’s authenticator field:
  1. Open the vault item in Bitwarden
  2. Click “Authenticator Key (TOTP)”
  3. Enter your TOTP secret or scan the QR code
  4. Skyvern retrieves both password and TOTP when using this credential
Supported TOTP formats:
  • Raw secret: JBSWY3DPEHPK3PXP
  • otpauth URI: otpauth://totp/Example:user@example.com?secret=JBSWY3DPEHPK3PXP&issuer=Example

1Password

Store TOTP in 1Password’s one-time password field:
  1. Edit the login item in 1Password
  2. Add a “One-Time Password” field
  3. Enter the TOTP secret or scan the QR code
  4. Reference the item in your Skyvern workflow

Multi-field TOTP entry

Some sites split TOTP codes across multiple input fields (one digit per box). Skyvern handles this automatically:
  1. Detects multi-field TOTP layouts
  2. Enters the same code across all fields
  3. Caches the code to prevent requesting a new one mid-entry
No special configuration needed. Skyvern’s AI recognizes multi-field TOTP inputs and handles them correctly.

Timeouts and polling

Skyvern waits for 2FA codes based on configurable timeouts:
SettingDefaultDescription
Polling interval10 secondsHow often Skyvern checks for new codes
Polling timeout15 minutesMaximum wait time before failing
If you’re pushing codes, ensure your forwarding pipeline delivers codes within the timeout window.

List recent codes

Debug your 2FA integration by listing recent codes received:
curl -X GET "https://api.skyvern.com/v1/credentials/totp?totp_identifier=user@example.com&limit=10" \
  -H "x-api-key: $SKYVERN_API_KEY"
Query parameters:
ParameterDescription
totp_identifierFilter by identifier (email, phone, etc.)
workflow_run_idFilter by specific workflow run
otp_typeFilter by type: totp or magic_link
limitNumber of records (default 50, max 200)
Skyvern only returns codes from the last 10 minutes (configurable via TOTP_LIFESPAN_MINUTES).

Next steps

Store Credentials

Set up your credential vault integration

Troubleshooting

Debug 2FA and login failures