ScreenshotNeo

BlogHow-to

Playwright Codegen: Record Browser Actions to Generate Tests

Record browser flows with Playwright Codegen, review its generated locators and assertions, and turn the result into a reliable test.

By the ScreenshotNeo team4 October 20269 min read

Playwright Codegen opens a browser and Playwright Inspector, records your interactions, and generates test code you can copy into your project. Run npx playwright codegen https://demo.playwright.dev/todomvc, perform the flow in the opened browser, add any useful assertions with Inspector’s assertion controls, then copy and review the generated code. Codegen is a strong starting point: check that its locators target the intended elements and that its assertions verify the behavior you care about.

1. Install Playwright and start Codegen

From a JavaScript or TypeScript project, install Playwright Test if it is not already installed:

npm init playwright@latest

Follow the prompts to choose a language and set up the project. Then launch Codegen with a URL:

npx playwright codegen https://demo.playwright.dev/todomvc

To start without a URL, run npx playwright codegen and navigate to the site in the browser that opens. The command syntax is npx playwright codegen [options] [url]. The CLI and guide are documented in the Playwright test generator guide and CLI reference.

2. Record a useful browser flow

  1. In the Codegen browser, navigate to the page or begin from the supplied URL.
  2. Perform the user actions the test should cover: click, fill fields, navigate, or select items.
  3. Watch the generated code in Playwright Inspector. Codegen records interactions and proposes locators based on the rendered page.
  4. Use Inspector’s assertion controls when you need a check. The documented controls can generate visibility, text, and value assertions.
  5. Stop recording, copy the generated code, and place it in your test file.

Record a scenario with a clear outcome, not every exploratory click. For example, a useful sign-in test might fill credentials, submit the form, and assert that a signed-in heading appears. Avoid including real passwords or personal data in recorded code.

3. Example: turn a recording into a runnable test

A generated test is a draft. This example shows the shape of a small Playwright Test in JavaScript, including a web-first assertion that waits for the expected result:

import { test, expect } from '@playwright/test';

test('adds a todo item', async ({ page }) => {
  await page.goto('https://demo.playwright.dev/todomvc');
  await page.getByPlaceholder('What needs to be done?').fill('Review Codegen output');
  await page.getByPlaceholder('What needs to be done?').press('Enter');
  await expect(page.getByText('Review Codegen output')).toBeVisible();
});

Save it as a test file such as tests/todo.spec.js in a Playwright Test project, then run:

npx playwright test tests/todo.spec.js

Use the locator and page structure that Codegen actually produces for your target site; accessible names and placeholders vary by application. For reliable tests, verify the expected outcome instead of assuming that completing an action means the application accepted it.

4. Review generated locators and assertions

Codegen analyzes the rendered page and prioritizes role, text, and test ID locators. If a locator matches multiple elements, it tries to refine it so it identifies the intended target. That helps produce readable code, but it cannot determine whether the chosen target represents the right product behavior.

  • Check the target: confirm each click or fill addresses the intended control, particularly when a page has repeated labels or buttons.
  • Prefer user-facing locators: use locators such as page.getByRole() when they describe how a person identifies the control. See the locator guide.
  • Use test IDs deliberately: if your team uses a test ID attribute, configure Codegen to match it with --test-id-attribute.
  • Assert outcomes: an action succeeding does not prove the intended state changed. Assert meaningful text, visibility, or values.
  • Prefer web-first assertions: assertions such as await expect(locator).toBeVisible() wait and retry for the condition. A one-time visibility read can fail during normal rendering delays. See Playwright’s best practices.

Locators are resolved against the current DOM when an action runs, which helps when the DOM changes between actions. Still, a locator that happens to be unique today may become ambiguous after a page update, so keep the test focused on stable user-facing behavior.

5. Configure the browser, output, and language

Use the installed Playwright version’s CLI help to check options available in your project:

npx playwright codegen --help

Common options documented for Codegen include:

Option Purpose
--browser Select Chromium, Firefox, or WebKit. Chromium is the documented default.
--output Write the generated script to a file.
--target Select the generated language or test target. Confirm supported target names with your installed version.
--test-id-attribute Set the attribute Codegen should treat as a test ID.
--viewport-size Generate while using a chosen viewport size.
--device Emulate a device profile, including its viewport and user agent.
--color-scheme Emulate a preferred color scheme.
--timezone, --geolocation, --lang Set the browser context’s timezone, location, or language for the recording.
--save-storage, --load-storage Save browser storage state after recording or load it for a later session.
--user-data-dir Use a browser profile directory. Chrome 136 and later prevent automated tools from accessing the default user data directory, so use a separate directory.
--http-credentials Provide HTTP Basic Authentication credentials.

For example, to generate a script file against a URL using Firefox, consult --help for the exact target name accepted by your installed version, then use the documented options in this form:

npx playwright codegen --browser firefox --output=recorded-test.js https://example.com

Language target names and combinations can be version-sensitive. Check the CLI reference and local help instead of assuming an option value from another Playwright release.

6. Authentication and browser state

When a flow requires a logged-in session, Codegen can save storage state for reuse and load it in another recording session. The saved state can include cookies, local storage, and IndexedDB data. Treat the resulting file as a credential:

  1. Save state to a project-local file that is excluded by .gitignore.
  2. Load it for a later session with --load-storage, using the same protected file.
  3. Delete the file when no longer needed, and never commit it with the test source.

HTTP Basic Authentication has a separate risk: the Codegen guide notes that supplied credentials are sent to any origin requesting them during recording and are included in generated code. Use only a controlled recording session, and remove credentials from files before sharing or committing them. See the authenticated state guidance.

For custom context setup, the guide also describes using page.pause() in a headed browser so you can configure a browser context before opening Codegen controls. That is useful when a simple CLI option does not provide the setup needed for the flow.

7. Pick a locator or extend an existing test

You do not always need a full recording:

  • Generate only a locator: stop recording, select the locator picker, hover to preview candidates, select the desired element, then copy or edit the locator.
  • Add steps to an existing test in VS Code: put the cursor where the new steps belong and use the extension’s Record at cursor workflow.
  • Use the VS Code locator picker: the Playwright extension also offers locator selection without recording an entire flow.

Choose the standalone Codegen and Inspector workflow to create a new flow, the editor integration when you want to insert actions into a test, and locator picking when you only need a selector. The VS Code guide explains its editor workflow.

8. Or skip the browser setup

If your task is to capture a page image or PDF rather than generate a browser test, ScreenshotNeo returns a screenshot from one GET request. The API accepts common screenshot API parameter names, which can make switching straightforward. 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}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
await Bun.write('shot.webp', res);

Replace YOUR_API_KEY with your key. The API can return PNG, JPEG, WebP, or PDF. ScreenshotNeo accepts cookie and consent banners as a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each step can be turned off. Bot checks and CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing, and response headers identify the page verdict and whether it was billed. Its MCP server provides take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients. The free plan includes 1,000 screenshots a month without a card; paid plans start at $5 for 3,000 screenshots.

Sign up free for 1,000 screenshots a month, with no card required.

9. Troubleshooting

Problem Likely cause What to do
The command is not found or Codegen does not launch. Playwright is not installed in the project, or the command is being run outside the expected project context. Install Playwright Test with npm init playwright@latest, then run npx playwright codegen --help from the project.
The browser opens at the wrong page. No URL was supplied, or the target flow begins elsewhere. Pass the URL after the options or navigate to it in the opened browser.
A generated locator is ambiguous or points to the wrong item. The page contains repeated labels or similar controls. Use the locator picker to inspect the target, choose a more specific user-facing locator, or add a stable test ID contract.
The recorded test is flaky around navigation or loading. The script may assume an immediate state change or rely on a one-time check. Add a web-first assertion for the intended result, such as visibility or expected text, so Playwright waits for the condition.
The page behaves differently from a real user’s device or locale. The recording context uses a different viewport, device, language, timezone, location, or color scheme. Record with the relevant context options, then keep the same context in the test configuration.
The existing Chrome profile cannot be reused. Chrome 136 and later block automated tools from accessing the default user data directory. Use a separate profile directory with --user-data-dir.
Authentication data appears in a generated file or repository. Storage state or HTTP credentials were saved with test output. Remove the secrets, protect storage files with .gitignore, rotate exposed credentials if needed, and delete unneeded state files.
An option from an example is rejected. The installed Playwright release may accept different targets or option values. Check npx playwright codegen --help and the CLI reference for the installed version.

10. Performance, reliability, and maintenance

Codegen is an interactive recording tool, so its run time depends on the site, browser, and actions in the flow. Keep the recorded test narrow: short scenarios are easier to review and diagnose than a long tour through unrelated pages. Reuse saved authentication state only when it is needed and keep it protected.

For reliability, prefer locators that reflect accessible roles, names, and stable test IDs; assert the result that matters; and review the generated script whenever the UI changes. Codegen helps build tests but cannot decide whether the scenario covers the right edge cases, whether an assertion is meaningful, or whether the recorded test’s credentials are safe to commit.

Codegen is part of Playwright, so no separate Codegen purchase is described in the cited documentation. The main operational costs are developer time to review and maintain tests and the infrastructure used to run the test suite. No benchmark or runtime guarantee is established by the sources used here.

11. Frequently asked questions

Can Codegen generate just one locator?

Yes. Use the locator picker, preview the candidate, select the element, and copy or edit the locator without keeping a full action recording.

Can it record a test in Python?

Yes. Codegen supports language targets; use --target and confirm the exact target value with the CLI help for your installed version.

Does a generated test need editing?

Usually it needs review. Confirm that its locators identify the right controls and that its assertions describe the outcome the test is meant to protect.

Can I add recorded actions to an existing test?

Yes. In VS Code, place the cursor at the insertion point and use Record at cursor to insert additional recorded actions.