Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.

Short answer: Chrome DevTools Recorder does not provide a documented Python export for its Puppeteer format. Recorder’s Puppeteer export is JavaScript for Node.js. To run the same user flow in Python, keep the Recorder JSON (or use the generated JavaScript as a reference), then translate each action to Playwright Python or Selenium. If you need to replay the original JSON without translating it, use Puppeteer Replay in its JavaScript/Node ecosystem instead.

What Chrome Recorder actually exports

DevTools Recorder stores a flow as a sequence of actions: navigation, element selection, typing, clicks, waits and checks. Its export options include JSON and Puppeteer-based formats. The Puppeteer export produces JavaScript; it is not a Python script that can be imported and executed by a Python interpreter.

That leaves three practical routes:

  • Translate the flow to Python: use Playwright’s Python API or Selenium’s Python WebDriver bindings.
  • Replay the recording with minimal translation: keep the JSON and run it with Puppeteer Replay, which is a Puppeteer/JavaScript tool rather than a Python runtime.
  • Use the generated Puppeteer file as a map: inspect its selectors, inputs and ordering while writing an equivalent Python test.

The exact conversion depends on the recorded website, browser version, operating system and test runner. An automatically translated flow is not guaranteed to keep working when the target page changes, so plan to validate and repair selectors and waits.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Recommended workflow: Recorder JSON to Python

  1. Record and verify the flow. In Chrome DevTools, open Recorder, create or select the user flow, and run it once while the page is in the state you expect.
  2. Export JSON. Use the Recorder export menu and save the JSON user flow. Keep this as the editable description of the actions. You can also export Puppeteer JavaScript to inspect the generated selectors and navigation behavior.
  3. Choose a Python library. Playwright is a good fit when you want synchronous or asynchronous APIs and support for Chromium, Firefox and WebKit. Selenium is appropriate when your project already uses WebDriver conventions.
  4. Install the package and browser components. Follow the current installation instructions for your chosen library. Playwright projects normally install the Python package and then the browser binaries; Selenium projects install the Python binding and use the Chrome/WebDriver setup supported by the installed versions.
  5. Map every action. Convert navigation, selectors, typed values, clicks, viewport settings, pop-ups, waits and assertions one by one. Preserve the order, but replace brittle timing with state-based waits where possible.
  6. Run against the real target. Treat the first run as validation. Repair selectors when labels, DOM structure or frames differ from the recording, and add an assertion for the outcome that matters to your test.

Playwright Python translation

The Playwright library can be used as a general purpose browser automation tool, providing APIs for web applications in both synchronous and asynchronous Python. The following is a complete synchronous starting point. Replace the URL, selectors and values with the actions in your Recorder flow.

from playwright.sync_api import sync_playwright

TARGET = "https://example.com/login"

with sync_playwright() as p:
    browser = p.chromium.launch(headless=True)
    page = browser.new_page(viewport={"width": 1440, "height": 900})

    page.goto(TARGET, wait_until="domcontentloaded")
    page.get_by_label("Email").fill("[email protected]")
    page.get_by_label("Password").fill("replace-with-a-test-secret")
    page.get_by_role("button", name="Sign in").click()

    # Express the intended result, not merely a delay.
    page.get_by_role("heading", name="Dashboard").wait_for()
    print(page.url)

    browser.close()

For an asynchronous test runner, use the async API and await each operation:

import asyncio
from playwright.async_api import async_playwright

async def main():
    async with async_playwright() as p:
        browser = await p.chromium.launch(headless=True)
        page = await browser.new_page(viewport={"width": 1440, "height": 900})
        await page.goto("https://example.com", wait_until="domcontentloaded")
        await page.get_by_role("link", name="Pricing").click()
        await page.get_by_role("heading", name="Plans").wait_for()
        await browser.close()

asyncio.run(main())

Recorder may emit CSS or XPath-like selectors rather than accessible roles. You can use a locator such as page.locator("form input[name='email']"), but prefer a stable role, label, test id or distinctive text when the application provides one. If the action occurs inside an iframe, locate the frame first and then use its locator. If a click opens a new tab, wait for the popup while performing the click:

with page.expect_popup() as popup_info:
    page.get_by_role("link", name="Open report").click()
report = popup_info.value
report.get_by_role("heading", name="Report").wait_for()

Selenium Python translation

Selenium’s Python binding uses WebDriver commands. This example starts Chrome, navigates, interacts with elements and waits for a result. The selectors are illustrative; copy the intent of your Recorder actions rather than assuming these exact selectors exist on your site.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

options = webdriver.ChromeOptions()
options.add_argument("--headless=new")
driver = webdriver.Chrome(options=options)
wait = WebDriverWait(driver, 20)

try:
    driver.set_window_size(1440, 900)
    driver.get("https://example.com/login")
    wait.until(EC.visibility_of_element_located((By.NAME, "email"))).send_keys("[email protected]")
    driver.find_element(By.NAME, "password").send_keys("replace-with-a-test-secret")
    driver.find_element(By.CSS_SELECTOR, "button[type='submit']").click()
    wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, "h1.dashboard")))
    print(driver.current_url)
finally:
    driver.quit()

WebDriver setup is version-sensitive: Chrome, the driver and Selenium must be compatible according to the current Selenium and browser documentation. Keep the browser session in a try/finally block so failed tests do not leave processes behind.

How to translate common Recorder actions

Recorder intent Playwright Python Selenium Python
Navigate page.goto(url) driver.get(url)
Type into a field locator.fill(value) element.send_keys(value)
Click locator.click() element.click()
Select an option locator.select_option("value") Select(element).select_by_value("value")
Wait for a condition locator.wait_for() or an assertion WebDriverWait(...).until(...)
Read text locator.inner_text() element.text
Set viewport browser.new_page(viewport={...}) driver.set_window_size(width, height)

Recorder’s generated JavaScript can reveal whether an action expects navigation, a dialog, a new page or a particular selector. Recreate that behavior explicitly in Python. For authentication, use a dedicated test account and inject secrets through environment variables rather than committing them to the script.

Replay the original JSON instead of converting it

Puppeteer Replay is the closest documented route to running a Recorder JSON flow with minimal translation. It provides a command-line and API workflow for Recorder JSON and supports customization and transformation. It remains a JavaScript/Puppeteer solution, so it does not turn the flow into Python or let a Python test runner execute it directly.

Choose this route when preserving the original recording matters more than using Python. Choose Playwright or Selenium when the flow must live in a Python test suite, share Python fixtures, or run under a Python CI framework.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Selectors, waits and assertions that survive translation

Prefer stable selectors

Generated selectors often depend on DOM nesting, classes or transient text. Prefer an accessible label, role, name or application-provided test identifier. If no stable hook exists, ask the application team for one instead of adding increasingly complex XPath.

Wait for state, not time

A fixed sleep may pass on a fast machine and fail under CI load. Wait for the element to be visible, enabled or attached; wait for a URL change or a response when navigation is the outcome. Use a short delay only when the application has a documented animation or debounce that cannot be observed another way.

Assert the business result

A successful click is not proof that the flow worked. Assert a heading, URL, confirmation message, downloaded file or other state that represents completion. Keep assertions close to the action that should cause them so failures identify the broken step.

Troubleshooting translated flows

  • “Element not found” or timeout: confirm the page URL, wait for the correct state, inspect whether the element is inside an iframe, and replace a generated selector with a stable role, label or test id.
  • Click intercepted: a consent banner, modal or sticky overlay may cover the target. Handle the overlay as a recorded step, wait for it to disappear, or select the intended element more precisely.
  • Typing has no effect: ensure the field is visible and enabled, and use the library’s fill/send-keys operation after focusing the correct frame.
  • Navigation race: combine the click with an explicit navigation or URL wait. For a new tab, wait for the popup before addressing its page.
  • Works headed but fails headless: set a deterministic viewport, check responsive breakpoints, remove assumptions about mouse position, and capture a screenshot or DOM dump at failure.
  • Intermittent failures: eliminate fixed sleeps, wait on network or visible state where appropriate, isolate test data, and ensure each run starts with a clean context.
  • Browser startup failure: verify that Playwright’s browser binaries are installed or that Selenium’s Chrome/driver versions are compatible; also check CI sandbox and display requirements.
  • Recorder flow changed: re-record the affected action, compare the JSON or generated JavaScript with the current DOM, and update the Python mapping rather than blindly retrying.

Performance, reliability and cost decisions

Headless mode usually reduces display overhead, while reusing a browser process can reduce startup time. Do not reuse pages or authentication state across tests unless shared state is intentional; isolation makes failures easier to reproduce. Run a small smoke flow first, then parallelize independent contexts only after the target site and test data can tolerate concurrent sessions.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Browser automation consumes CPU, memory, network bandwidth and time. Failed translations cost developer time rather than a special API fee, but CI minutes and hosted browser resources still matter. Keep recordings short, avoid unnecessary full-page waits, and collect artifacts only on failure. The sources do not establish a success rate for any automatic converter, so treat every conversion as code that requires review.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Or skip the browser setup

If your requirement is simply to capture the resulting page rather than replay every interaction, ScreenshotNeo provides a single website-screenshot request. It accepts consent banners like a visitor and removes more than 60 known consent platforms, newsletter popups and chat widgets before capture; each of those cleanup steps can be turned off. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads and cache hits are not billed, and the response identifies the result with X-Page-Verdict and X-Billed headers.

Use the API documentation at https://screenshotneo.com/docs/ for the full option set. A basic call is:

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

The same request in Python:

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)

And in Node.js:

const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

ScreenshotNeo also offers an MCP server with take_screenshot, get_page_info and capture_pdf tools for Claude, Cursor and other MCP clients. Features include full-page lazy-image capture, CSS-element capture, device presets, custom viewport and retina scale, PDF controls, custom CSS and JavaScript, clicks, selector or network-idle waits, request blocking, headers, cookies, user agents, authorization, timezone, geolocation, transparent backgrounds, resizing, configurable caching, signed links, asynchronous webhooks, bulk capture of up to 100 URLs per call, a usage API and an OpenAPI specification.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

The Free plan includes 1,000 screenshots per month with no card. Paid plans start at $5 for 3,000 screenshots; every feature is available on every plan. Create a free ScreenshotNeo account to try it without a card.

FAQ

Can I import a Recorder JSON file directly into Python?

Not as a documented native Python runtime. Use the JSON as the source for a Playwright or Selenium translation, or replay it with Puppeteer Replay.

Should I choose Playwright or Selenium?

Choose Playwright for its sync/async Python APIs and broad browser support; choose Selenium when your organization already standardizes on WebDriver and its surrounding tooling.

Is the generated Puppeteer JavaScript useless if I want Python?

No. It is a useful reference for action order, selectors, navigation and expected page state, even though it cannot be executed by Python unchanged.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Frequently Asked Questions

Can I import a Recorder JSON file directly into Python?

Not as a documented native Python runtime. Use the JSON as the source for a Playwright or Selenium translation, or replay it with Puppeteer Replay.

Should I choose Playwright or Selenium?

Choose Playwright for its sync/async Python APIs and broad browser support; choose Selenium when your organization already standardizes on WebDriver and its surrounding tooling.

Is the generated Puppeteer JavaScript useless if I want Python?

No. It is a useful reference for action order, selectors, navigation and expected page state, even though it cannot be executed by Python unchanged.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.