How to Generate Playwright Tests with Codegen
Record browser flows with Playwright Codegen, add assertions, choose locators, and turn the generated code into maintainable tests.
Playwright Codegen records browser interactions and turns them into starter test code. In a project with Playwright installed, run npx playwright codegen https://your-site.example, perform the flow in the opened browser, add assertions in Playwright Inspector, then stop and copy the generated code into your test file. Review and refine the result before relying on it: a recording captures actions, but you still need to decide which outcomes matter and how the test fits your project.
1. Set up Playwright
Codegen is included with Playwright. If your project already uses Playwright, use its installed version and package scripts. Otherwise, the official getting-started workflow can create a project and install the test runner:
npm init playwright@latest
Follow the prompts to choose JavaScript or TypeScript, whether to add a GitHub Actions workflow, and where to put tests. Check the official Playwright installation guide for current setup details.
Run Codegen from the project directory so the browser, generated syntax, and test setup correspond to the installed Playwright version.
2. Record a browser flow with the CLI
- Start Codegen for the page you want to exercise:
npx playwright codegen https://your-site.example
A browser opens for the interactions, and Playwright Inspector displays generated code. You can omit the URL and enter it in the browser after launch:
npx playwright codegen
- Perform a representative journey as a user would: open a page, navigate, fill fields, click controls, and reach the result you need to check.
- Use Inspector’s assertion control to select important outcomes. Documented assertion choices include visibility, text, and value.
- Stop recording. Inspect the output, then copy it into a test file or use the output-file option described below.
- Run the test, then edit it to make the intent and expected behavior explicit.
Record a focused journey rather than every possible action. A useful test should make clear what user behavior it covers and what result proves that behavior worked.
3. Add checks, not just actions
A script that clicks and types can finish without establishing that the application behaved correctly. Add assertions for meaningful results: a confirmation appears, a value changes, or a destination page becomes visible. You can add supported assertions while recording in Inspector, then review them in the test file.
For example, a generated test may start like this:
import { test, expect } from '@playwright/test';
test('user can complete a search', async ({ page }) => {
await page.goto('https://your-site.example');
await page.getByRole('textbox', { name: 'Search' }).fill('playwright');
await page.getByRole('button', { name: 'Search' }).click();
await expect(page.getByRole('heading', { name: 'Search results' })).toBeVisible();
});
This is an illustrative, runnable test shape; your actual locators and expected heading must match the site. Codegen’s output varies with the page and actions you record.
4. Review and improve generated locators
Codegen prioritizes locators based on roles, text, and test IDs, and attempts to disambiguate when more than one element matches. Treat each generated locator as a suggestion to review, not a guarantee that it expresses the test’s intent.
- Prefer user-facing semantics when appropriate.
getByRole()with an accessible name usually states what a person interacts with, such as a button or heading. - Use an explicit test ID for an intentional test contract. Test IDs can be useful when visible text is variable or when the team has deliberately designated a stable hook.
- Check uniqueness and meaning. A locator that matches two elements may be ambiguous; a positional selector can silently point at the wrong one if the page changes.
- Use Pick Locator to inspect alternatives. After stopping the recording, choose Pick Locator, select the target, and review the suggested locator in the locator playground before copying it.
- Configure a custom test ID attribute if needed. If the application uses an attribute other than the default, set it with
--test-id-attributeso Codegen recognizes the project’s convention.
See the Playwright locator guide for locator behavior and recommendations.
5. Choose how and where code is generated
CLI options
The general command form is:
npx playwright codegen [options] [url]
| Option | Use | Example |
|---|---|---|
--target |
Choose the generated language or test framework target supported by the installed CLI. | npx playwright codegen --target=python https://your-site.example |
-o |
Write generated output to a file. | npx playwright codegen -o tests/recorded.spec.ts https://your-site.example |
-b |
Select a browser: chromium, firefox, or webkit. |
npx playwright codegen -b firefox https://your-site.example |
--test-id-attribute |
Set the attribute Codegen should treat as the test ID. | npx playwright codegen --test-id-attribute=data-pw https://your-site.example |
Available targets and exact option behavior can depend on the installed Playwright release. Check the official Codegen documentation when using a version-sensitive flag.
VS Code extension
The Playwright VS Code extension offers recording in the editor. In the Testing sidebar, choose Record new to create a test, or record at the cursor to add actions to an existing test. The recording toolbar also provides assertion controls. You can use the locator picker to copy a locator. This workflow is convenient when you want the generated code to land directly in the editor; inspect and edit it just as you would CLI output. See the official recording documentation.
6. Record under the conditions your test needs
Codegen supports browser and context options for matching the scenario you intend to test. Use the relevant settings when viewport, device behavior, color scheme, locale, time zone, or location affects the flow.
# Set a viewport
npx playwright codegen --viewport-size="800,600" https://your-site.example
# Emulate a device
npx playwright codegen --device="iPhone 13" https://your-site.example
# Emulate dark color scheme
npx playwright codegen --color-scheme=dark https://your-site.example
Other documented context options include --timezone, --geolocation, and --lang. Consult the Codegen guide for current syntax and supported device names. Record with conditions that match the intended test; otherwise, the generated flow may reflect a different layout or locale.
7. Record a flow that requires authentication
For a logged-in journey, save browser state at the end of a recording and load it in a later session:
# Record a login flow and save state
npx playwright codegen --save-storage=auth.json https://your-site.example/login
# Reuse that state in a later recording
npx playwright codegen --load-storage=auth.json https://your-site.example/account
Saved state can include cookies, local storage, and IndexedDB data. It may be enough to impersonate the account. Keep auth.json local, add it to .gitignore, and delete it when it is no longer needed. Do not commit it or share it in logs or support tickets. Playwright’s authentication documentation explains the risks and storage-state workflow.
Codegen also supports --http-credentials for HTTP Basic Authentication. Credentials can be sent to any origin that requests them during the session and are included in generated code. Use only credentials appropriate for the recording, and review output before sharing or committing it.
8. Use a dedicated browser profile or custom context setup
--user-data-dir lets Codegen use a dedicated browser profile. Keep it separate from your normal profile. The Playwright guide notes that, since Chrome 136, the default Chrome user data directory cannot be accessed by automation; create and use a separate directory for testing.
For non-standard context setup, the documented pattern is to launch a headed browser, create a context, open a page, and call page.pause() to open Codegen controls:
import { chromium } from 'playwright';
const browser = await chromium.launch({ headless: false });
const context = await browser.newContext({
viewport: { width: 1280, height: 800 },
});
const page = await context.newPage();
await page.goto('https://your-site.example');
await page.pause();
Run this from a script with Playwright installed. Stop the browser when finished. For the current API and debugging workflow, see the official recording a script section.
9. Turn the recording into a maintainable test
- Give the test a behavior-focused name. Describe what the user can do or what outcome is expected.
- Remove irrelevant steps. Keep setup and actions that are needed to reach the behavior under test.
- Keep assertions close to outcomes. Check the result after the action that should cause it.
- Check selectors against the application contract. Prefer accessible names and roles when they identify the intended control; use test IDs when the team has chosen them as stable hooks.
- Fit the project’s conventions. Use its fixtures, setup, test naming, and configuration rather than leaving a standalone recording disconnected from the suite.
- Run it in the project’s normal test command. Investigate failures before concluding whether the application or the test needs a change.
- Review secrets and test data. Remove credentials, personal data, and unnecessary account details from generated code.
Generated code is a starting point. Review it in context and add checks for the behavior the test is meant to protect.
10. Troubleshooting
| Symptom | Likely cause | What to do |
|---|---|---|
npx playwright codegen is not found or prompts unexpectedly |
Playwright is not installed in the current project, or the command is running from a different directory. | Run it from the project directory and install Playwright using the official setup guide. Check the package manager and installed version. |
| The browser does not open | The browser binary may not be installed, the environment may not support a headed browser, or launch may have failed. | Install the browser binaries required by the project using Playwright’s documented install command. Run Codegen in a desktop session that can show a browser. |
| The generated test has actions but no useful checks | Assertions were not added during recording. | Use Inspector’s assertion control or add explicit assertions in the test after reviewing the expected outcome. |
| A locator is ambiguous or points to the wrong control | Multiple elements share the recorded text or role, or the page structure changed. | Use Pick Locator, inspect matches, and choose a locator that identifies the intended element. Add or use an explicit test ID if appropriate. |
| The recorded flow behaves differently on replay | The page, account state, viewport, device, locale, time zone, or location differs from the recording conditions. | Record with the needed emulation options and provide the right test state. Keep test data and setup repeatable. |
| The login flow is missing in a later recording | Saved storage state was not loaded, expired, or does not cover the authentication mechanism in use. | Regenerate the state, pass --load-storage, and confirm the session is valid. Protect the state file as a secret. |
| Chrome reports a profile or user-data-directory issue | Automation is trying to use the default Chrome profile, which is restricted for automation in Chrome 136 and later. | Create a separate profile directory and pass it with --user-data-dir. |
| Credentials appear in a generated file | HTTP credentials were supplied during Codegen and included in output. | Remove secrets from the file, rotate any credential that was exposed, and use a secure secret-management approach for the test environment. |
11. Performance, reliability, and cost
Codegen is a recording aid; the generated test still runs through Playwright and the browser, so its runtime depends on the flow, page, and project configuration. Keep recordings focused, avoid unnecessary interactions, and use the test runner’s standard project setup for repeatable execution. No universal runtime or reliability figure applies to every page or environment.
Codegen is part of Playwright, an open-source browser automation framework. The dossier does not specify a Codegen usage fee. Browser execution still consumes local or CI resources, so account for the runner and infrastructure your project uses. Reliability comes from clear assertions, suitable locators, controlled test data, and reviewing failures rather than treating a successful recording as proof that a test is complete.
Or skip the browser setup
If your goal is to capture a page image rather than generate a browser test, ScreenshotNeo is a website screenshot API and MCP server. A single GET request returns a PNG, JPEG, WebP, or PDF. See the ScreenshotNeo API documentation.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
- Cookie banners, newsletter popups, and chat widgets are removed before the shot; each cleanup step can be turned off.
- Bot checks, blank pages, failed loads, timeouts, and cache hits are not billed. Responses identify the page verdict and billing status in headers.
- An MCP server lets AI agents, including Claude and Cursor, take screenshots with tools for screenshots, page information, and PDF capture.
- 1,000 screenshots a month are free with no card. Paid plans start at $5 for 3,000 screenshots; every feature is on every plan.
Sign up for 1,000 free screenshots a month, with no card required.
12. FAQ
Does Codegen write a finished test automatically?
It generates code from browser interactions. You should review the locators, add or verify assertions, and adapt the output to your project.
Can I start Codegen without a URL?
Yes. Run npx playwright codegen and enter the address in the opened browser.
Can I record in Python?
Yes. Use the CLI target option, for example npx playwright codegen --target=python https://your-site.example.
How do I keep a signed-in session for recording?
Save state with --save-storage and load it later with --load-storage. Treat the saved file like a credential.
Can Codegen help when I only need a page screenshot?
Codegen’s purpose is recording browser actions into code. For a screenshot or PDF capture through one request, see ScreenshotNeo’s API documentation.


