Automate MFA Testing with Playwright — Tutorial, Code & Best Practices

🚀 Introduction & Context
How to automate E2E tests with MFA enforced is a common questions when working on test automation. When applications implement Multi-Factor Authentication for security, traditional test automation approaches break down, forcing teams to either disable MFA in test environments (which is a bad idea) or going back to manual testing or even not testing MFA flows!. This guide aimes to demonstrate how to automate end-to-end tests with MFA enabled thanks to GetMyMFA features.
This hands-on guide shows how to automate an end-to-end login secured by SMS-based Multi-Factor Authentication, using Playwright and the GetMyMFA API. You can adapt the same pattern to any other critical flow like financial transactions or sensitive approvals.
Testing Multi-Factor Authentication workflows is a challenge for QA teams. As we explored in our article on overcoming MFA test automation challenges, traditional approaches often involve disabling MFA in test environments or manually handling verification codes, both of which compromise test reliability and security validation. This tutorial will show a production-ready approach that maintains security while enabling comprehensive automation.
🎯 What we'll build
In this tutorial, we'll create a complete Playwright test suite that automatically handles SMS-based MFA authentication. You'll learn to set up a TypeScript project, integrate with GetMyMFA's API, and build a robust test that can fetch verification codes programmatically and complete the entire login flow without manual intervention. By the end, you'll have a production-ready testing solution that you can adapt for your own applications. Complete source code is available for download at the end of this article.
🔄 Overview: How the flow works
The end-to-end flow below mirrors a real user experience and avoids insecure test-only shortcuts:
- Start sign-in. Your test framework launches a login attempt against the demo app.
- App sends SMS. The app sends an MFA code by SMS to a GetMyMFA virtual number.
- Code exposed via API. GetMyMFA exposes the SMS securely via API.
- Fetch the code. Your test retrieves the latest code from the API.
- Submit the code. The test injects it into the form and completes authentication.

Note: In this demo, the actual SMS send (step 2) is skipped to avoid cost; the rest remains fully automated.
🛠️ Tutorial: Set up Playwright + GetMyMFA
1️⃣ Initialize a Playwright (TypeScript) project
Start by creating a new Playwright project with TypeScript support:
npm init playwright@latest
Choose TypeScript, confirm tests in the tests
folder, skip GitHub Actions if you like, and install Playwright browsers when prompted.

Your project structure should look like this:

2️⃣ Create a GetMyMFA test account + API key
Visit get.mymfa.io and select Sign Up. The Trial option gives you a temporary virtual number with API access. Then open API Configuration to create an API key — store it securely.

3️⃣ Get your virtual phone number ID
Add your key as a header, x-api-key
, and call:
GET https://programmatic-api.client.get.mymfa.io/v1/phone-numbers
The response includes phoneId
. To fetch the most recent code:
GET https://programmatic-api.client.get.mymfa.io/v1/<YOUR_PHONE_ID>/mfa/latest
The MFA code is in mfaCode
.

If you are curious about how the MFA code is returned, you can run the second API call through postman:

4️⃣ Add a helper to fetch the latest MFA code
export async function getMfaCode(phoneId: string, apiKey: string) {
try {
const headers = {
'x-api-key': apiKey,
'Content-Type': 'application/json',
};
const response = await fetch(`https://programmatic-api.client.get.mymfa.io/v1/${phoneId}/mfa/latest`, { headers });
const data = await response.json();
const mfaCode = data.mfaCode;
return mfaCode;
} catch (error) {
console.error('MFA retrieval error', error);
throw error;
}
}
5️⃣ Keep secrets out of your code
import { test, expect } from '@playwright/test'
import * as dotenv from 'dotenv'
dotenv.config()
const PHONE_NUMBER_ID = process.env.GETMYMFA_PHONE_NUMBER_ID!
const API_KEY = process.env.GETMYMFA_API_KEY!
const TEST_USER_EMAIL = process.env.TEST_USER_EMAIL!
const TEST_USER_PASSWORD = process.env.TEST_USER_PASSWORD!
const GETMYMFA_DEMO_URL = 'https://demo.mymfa.io/login'
6️⃣ Put it together in a Playwright test
test('E2E Login with SMS-based MFA', async ({ page }) => {
// Navigate to the demo page and confirm title
await page.goto(GETMYMFA_DEMO_URL)
await expect(page).toHaveTitle(/GetMyMFA/)
// Fill in login fields and start sign-in
await page.getByRole('textbox', { name: 'Email' }).fill(TEST_USER_EMAIL)
await page.getByRole('textbox', { name: 'Password' }).fill(TEST_USER_PASSWORD)
await page.getByRole('button', { name: 'Login', exact: true }).click()
// Ensure MFA prompt is visible
await expect(page.getByText('MFA Time')).toBeVisible()
// Fetch MFA code via GetMyMFA API
const mfaCode = await getMfaCode(PHONE_NUMBER_ID, API_KEY)
// Submit code and confirm success
await page.getByRole('textbox', { name: 'MFA Code' }).fill(mfaCode)
await page.getByRole('button', { name: 'Submit' }).click()
await expect(page.getByText('MFA code verified')).toBeVisible()
})
✅ Best Practices for MFA Test Automation
🔒 Security Considerations
- Environment Isolation: Use dedicated test environments with separate MFA configurations
- API Key Management: Store API keys as environment variables or CI secrets, never in source code
🎯 Test Reliability
- Stable Selectors: Use data-testid attributes or stable IDs rather than CSS classes
- Retry Logic: Implement retries for MFA code retrieval with exponential backoff
🚀 CI/CD Integration
- Parallel Execution: Use unique virtual numbers for parallel test runs
- Environment Variables: Configure API credentials through CI environment variables
- Monitoring: Set up alerts for test failures related to MFA workflows
💭 Final thoughts
Automating MFA testing with Playwright and GetMyMFA enables comprehensive end-to-end testing without compromising security. This approach ensures that critical authentication flows are thoroughly validated in conditions that mirror production environments.
By integrating realistic MFA testing into your automation suite, you can catch integration issues early, validate user experience flows, and maintain confidence in your application's security mechanisms. The investment in proper MFA test automation pays dividends in reduced manual testing effort and increased deployment confidence.
Start automating your MFA workflows today and bring production-like security validation to your testing pipeline. Your QA team and users will benefit from the improved reliability and security assurance.
Ready to automate your MFA testing?
Start with a free trial • No credit card required • Full API access