Skip to content

Playwright and Your Real Chrome Profile: Why It Stopped Working, and What Works Now

The old trick — debug port on your everyday Chrome, connect over CDP, automate with your real logins — was deliberately killed for security. If your script cannot attach or launches signed out of everything, this is why. Here are the patterns we actually run in production.

August 20, 20268 min readShift The Culture

The old trick — launch your everyday Chrome with --remote-debugging-port=9222, connect Playwright or Puppeteer over CDP, and automate with all your real logins — stopped working in 2025. If your script suddenly cannot attach, the port never opens, or Chrome launches signed out of everything, you are hitting a deliberate Chrome security change, not a bug in your code. Here is what changed, and the profile patterns we run in production instead.

What changed: Chrome 136 killed debugging the default profile

From Chrome 136, --remote-debugging-port and --remote-debugging-pipe are ignored when Chrome is using the default user data directory. To get a debugging endpoint at all, you must also pass --user-data-dirpointing somewhere non-standard. Google's stated reason is solid: malware was abusing the debugging port to attach to real profiles and exfiltrate cookies and saved credentials, and a non-default data directory uses a different encryption key. The announcement is on the Chrome developers blog.

  • Symptom: Chrome opens normally but nothing listens on 9222; connect_over_cdp gets connection refused. No error, no warning — the flag is just not honored.
  • Corollary: every tutorial that says “point --user-data-dirat your existing Chrome profile folder” is now advice to fight both this restriction and Chrome's profile lock (a second Chrome on a profile that is already open fails or opens a temp profile).

The three patterns that work

  1. A dedicated automation profile you log in once (our default). Create a fresh directory, launch real Chrome — not bundled Chromium — through Playwright with launch_persistent_context(user_data_dir=…, channel="chrome", headless=False), and log into the sites you automate, once, by hand. The profile persists, so the sessions do too. Real Chrome plus a real, aged profile also survives bot-detection checks that instantly flag stock headless Chromium.
  2. A copy of a real profile, in a separate data dir. When re-logging-in is the hard part, copy the profile directory to a new location and launch Chrome with --user-data-dir=<copy> --remote-debugging-port=9223, then connect_over_cdp. This satisfies the Chrome 136 rule (non-default dir) and dodges the profile lock. Honest limits from our production use: it works for many sites, but Google's own sessions do not survive the copy— device-bound session credentials mean the copy reads “signed out” even though the cookie files came along. Plan for per-site re-auth in the copy.
  3. CDP into a Chrome you started yourself — never the one the human is using.If you must attach to a running Chrome, start that Chrome for automation, with its own data dir and port. We learned the never-share rule the hard way: an automation session once closed a window with fifteen of the operator's tabs, and a stuck native menu in a shared Chrome blocks all scripting against it. Assume any browser a human touches is shared, and give automation its own.
pattern 1 in ~six lines (Python)
from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    ctx = p.chromium.launch_persistent_context(
        user_data_dir="~/.myapp-automation-profile",   # NOT your real Chrome dir
        channel="chrome",                              # real Chrome, not Chromium
        headless=False,
    )
    page = ctx.new_page()

Detection, and what a real profile does not fix

A persistent real-Chrome profile fixes the fingerprint class of detection: stable cookies, plausible history, real GPU strings. It does not fix behavioral or endpoint checks, and pretending otherwise burns accounts. Things we have measured, so you do not have to:

  • Some hardened sites 403 Playwright-driven sessions even with a real profile and stealth patches — they fingerprint the automation driver, not the profile. For those, the remaining options are a real-Chrome CDP attach (pattern 2) or accepting the site is closed to you.
  • Synthetic events differ from real input in ways sites and even Chrome itself act on: a JavaScript .click() carries no user activation, so it cannot open a file picker — upload flows need set_input_files on the real <input>, a filechooserevent handler, or OS-level clicks. And we have watched synthetic clicks update a widget's visible text while the app's internal state stayed empty — readback of the DOM is not proof the app accepted the input.
  • Headed beats headless for reliability, not just detection: some SPAs simply do not mount in occluded or background tabs, and produce empty scrapes that look like broken selectors.

The profile decision, on one screen

choosing a pattern
Need real logins, sites you control the auth for
  → dedicated persistent profile, channel="chrome", log in once      (pattern 1)
Need an existing profile's sessions, re-login is painful
  → copy profile to new dir + --remote-debugging-port + CDP attach   (pattern 2)
  → expect Google sessions to be signed out in the copy (device-bound)
Must attach to running Chrome
  → only one YOU launched, own data dir, own port                    (pattern 3)
Never
  → automate the default profile dir, or any profile a human uses
  → trust a JS .click() for file pickers or state-committing widgets

If you are running several of these sessions alongside coding agents on one machine, the collision-avoidance rules are the same ones covered in running multiple coding agents on one machine — and when a scrape returns something surprising, check it against a second, differently-sourced read before acting on it; the reasoning is in agents saying done when they are not.

SharePost on X
Free · 13 pages · no upsell inside

Get the Operator Field Kit — free

Six production prompts, the five-step operator setup, and nine rules from our own failure log.

  • 6 complete prompts — printed in full, not previews
  • The five-step setup, each step with a pass/fail test
  • 9 rules from the failure log that produced them

The kit, then the occasional operator note. One click unsubscribes and we never sell the address.

Keep reading