惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

L
LINUX DO - 最新话题
C
Cyber Attacks, Cyber Crime and Cyber Security
G
GRAHAM CLULEY
T
Tenable Blog
T
Threatpost
C
CXSECURITY Database RSS Feed - CXSecurity.com
I
Intezer
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
D
Darknet – Hacking Tools, Hacker News & Cyber Security
K
Kaspersky official blog
Security Latest
Security Latest
P
Privacy & Cybersecurity Law Blog
Google Online Security Blog
Google Online Security Blog
SecWiki News
SecWiki News
P
Palo Alto Networks Blog
TaoSecurity Blog
TaoSecurity Blog
Webroot Blog
Webroot Blog
Spread Privacy
Spread Privacy
O
OpenAI News
The Last Watchdog
The Last Watchdog
P
Proofpoint News Feed
C
Check Point Blog
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
人人都是产品经理
人人都是产品经理
S
Security @ Cisco Blogs
Scott Helme
Scott Helme
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
月光博客
月光博客
S
Securelist
酷 壳 – CoolShell
酷 壳 – CoolShell
V
V2EX
T
Troy Hunt's Blog
W
WeLiveSecurity
GbyAI
GbyAI
N
News | PayPal Newsroom
Y
Y Combinator Blog
C
Cisco Blogs
H
Help Net Security
The GitHub Blog
The GitHub Blog
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
博客园 - 【当耐特】
Jina AI
Jina AI
MongoDB | Blog
MongoDB | Blog
P
Proofpoint News Feed
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
云风的 BLOG
云风的 BLOG
小众软件
小众软件
N
News and Events Feed by Topic

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant Common SOC 2 Failures (Real World) Stop Vibe-Checking Your AI App: A Practical Guide to Evals How to Use SonarQube and SonarScanner Locally to Level Up Your Code Quality Your Next To-Do App Is Dead — I Replaced Mine with an OpenClaw AI Sign a Nostr event in 60 lines of Python using coincurve — no nostr-sdk, no nbxplorer, no rust toolchain ITGC Audit Explained Like You’re in Big 4 Patch Tuesday abril 2026: Microsoft parcha 163 vulnerabilidades y un zero-day en SharePoint Stop scraping everything: a better way to track competitor price changes Listing on MCPize + the Official MCP Registry while routing payments OUTSIDE the marketplace — how I kept 100% of my x402 revenue Building an AI-Powered Risk Intelligence System Using Serverless Architecture Why We Ripped Function Overloading Out of Our AI Toolchain Testing AI-Generated Code: How to Actually Know If It Works SaaS Churn Is Killing Your Business. Here Is What to Do About It (Without a Support Team) The Speed of AI Is No Longer Linear - And Self-Improving Models Are Why How to Implement RBAC for MCP Tools: A Practical Guide for Engineering Teams From Standard Quote to Persuasive Proposal: AI Automation for Arborists I built a CLI that scaffolds complete multi-tenant SaaS apps Axios CVE-2025–62718: The Silent SSRF Bug That Could Be Hiding in Your Node.js App Right Now The dashboard that ended our friendship Data Pipelines Explained Simply (and How to Build Them with Python) The Hidden Cost of AI Systems Nobody Talks About. undefined vs undeclared, and how typeof behaves Switching from file-based jobs to NATS/Kafka in Rust without changing code io_uring Adventures: Rust Servers That Love Syscalls Why Agentic AI is Killing the Traditional Database The POUR principles of web accessibility for developers and designers Quantum Neural Network 3D — A Deep Dive into Interactive WebGL Visualization How To Install Caveman In Codex On macOS And Windows Automation Pipeline Reliability: Why Your Workflow Breaks When Nobody Is Watching I Built an 'Open World' AI Coding Agent — It Works From ANY Folder From Freelancing to Product: A Tech Service Company's SaaS Transformation China's AI Giants: Adding Tencent Hunyuan & ByteDance Doubao to AI University (74 Providers) On the Vibe Coders and Their Lies clerk: Auto-Summarize Your Claude Code Sessions AI Weekly — 2026/04/10–04/17 | The Model Lockdown Is Here, but the Toolchain Is the Real Battleground AI 週報 — 2026/04/10–2026/04/17 模型封鎖潮來了,但工具鏈才是真戰場 Maybe this is how Open-Source apps are born... 🚀 Fine-Tune LLMs with LoRA and QLoRA: 2026 Guide tRPC v11 + Next.js App Router: End-to-End Type Safety Without the Boilerplate ShadCN UI in 2026: Why I Stopped Installing Component Libraries and Started Owning My Components SaaS Billing in React Server Components: Stripe + Supabase Without a Single `useEffect` Join our DEV Weekend Challenge — $1,000 in Prizes Across TEN winners! Submissions Due April 20 at 6:59 AM UTC. Implementing FSRS Spaced Repetition in Flutter + Supabase — Adding Memory Science to an AI Learning App "I Texted My Localhost From the Train — Claude Code Fixed the Bug Before I Got Home" I Built a Sales Prep AI and It Went Deeper Than Expected Design to Code #2: One JSON, Eleven Outputs Solving the 100M-Row Problem: A Summary Table Pattern for High-Volume Push Notification Logs Flutter Web With Wasm: What Actually Changes For Developers I Built 50 Royalty-Free Soundtracks for My Side Project in a Weekend Using AI Music Generation The Vibe Coding Security Checklist: 7 Things to Check Before You Ship Stop Letting Googlebot Guess Fix Your React App's SEO Right Desconstruindo o Streaming do LinkedIn: Como Criar um Engine de Extração de Vídeo de Alta Performance com HLS e FFmpeg (EDA Part-1) EDA (Exploratory Data Analysis) Explained With Real Life — Why Looking at Your Data Is the Most Important Step in Machine Learning Brand Relationship Management at Scale: Our 4-Touch Outreach System for 200+ Brands Why String.fromEnvironment() Might Return an Empty String in Dart JGuardrails 1.0.0 — Hardening Java LLM Apps Against Jailbreaks, Toxicity, and Prompt Injection Plan and Schedule a Full Week of Threads Content From One Claude Conversation Coding Cat Oran Ep3, Five Tables Changed Everything Updated: BFF Pattern I'm done watching freelancers get buried by 200 proposals. So I'm building the alternative. This is my first post BFS Algorithm in Java Step by Step Tutorial with Examples Tracking LLM Pricing Monthly: An Open Dataset for 22 AI Models How We Measure Content ROI on a Comparison Site: Revenue Attribution Without Perfect Data Introducing Nova AI Ops: The AI-Native Operating System for SRE Teams I built a free desktop video downloader for Windows — Grabbit How Talkie OCR Helps Vision-Impaired & Dyslexic Users Read the World Around Them VRCFaceTracking安装和iPhone面捕配置教程,有bug Even CrowdStrike Can't See Your Agents The Automation Gold Rush: What n8n Workflows and Claude Are Opening Up for Developers Right Now
Debugging Playwright CDP Sessions That Lose Cookies and Proxy Context
ZP · 2026-05-30 · via DEV Community

I started treating this as a separate bug class after seeing the same failure pattern repeat:

A human opens a browser profile and is logged in.
A Playwright script attaches through CDP.
The page opens.
Then the workflow behaves as if the session is empty, the account is logged out, or the request is coming from the wrong proxy.

The tempting fix is to add waits or rewrite selectors.

That is usually the wrong first move.

When a CDP-attached session loses auth state or proxy context, the first question is not:

Which selector changed?

It is:

Did my script attach to the same browser identity that I verified manually?

This note is a practical debugging checklist for that problem.

Problem: Playwright attaches to an existing Chromium browser, but cookies, session state, or proxy context do not match what I expected.

Scope: Chromium, connectOverCDP, browser profiles, persistent sessions, headless checks, and AI agent debugging.

Not covered: bypassing platform protections, CAPTCHA handling, or moving auth data between unrelated accounts.

The failure pattern

The run usually looks healthy from the outside.

The browser starts. The CDP endpoint responds. Playwright connects. The page loads. The script can click and read the DOM.

But the environment is wrong.

You may see one or more of these symptoms:

  • Cookies are empty or fewer than expected.
  • The app redirects to login after refresh.
  • localStorage exists, but the app still treats the user as logged out.
  • The account works manually but fails when attached through CDP.
  • The public IP does not match the expected proxy route.
  • The task works in visible mode but fails in headless mode.
  • An AI browser agent retries the task and marks it successful from a different context.

That last case is especially easy to miss.

A normal script often stops when the environment changes. An AI agent may continue, adapt, and hide the real bug.

So before debugging selectors, I try to prove one thing:

The script is running from the expected browser identity.

First separate three persistence models

Before debugging, name the model you are actually using.

A lot of Playwright session bugs become confusing because these three models are mixed together:

  • storageState
  • launchPersistentContext
  • connectOverCDP

They are related, but they are not interchangeable.

1. storageState

storageState is a snapshot.

It is useful when auth is represented by cookies, localStorage, and sometimes IndexedDB.

It is not the same thing as a full browser profile.

Good fit:

  • test accounts
  • repeatable login setup
  • CI workflows
  • clean browser contexts

Risky assumption:

My real Chrome profile is logged in, so storageState must contain everything.

It may not.

Some apps also involve sessionStorage, service workers, extensions, device-bound state, or app-specific storage.

2. launchPersistentContext

launchPersistentContext starts a browser with a specific user data directory.

That directory stores browser session data such as cookies and localStorage.

Good fit:

  • long-lived automation profile
  • local debugging
  • workflows where the profile directory is the source of truth

Risky assumption:

I can point multiple browser instances at the same profile directory.

Do not do that.

Treat the user data directory like a lockable database. One browser owns it during the run.

3. connectOverCDP

connectOverCDP attaches Playwright to an existing Chromium browser over the Chrome DevTools Protocol.

Good fit:

  • attaching to a browser started by another tool
  • debugging an already-open profile
  • connecting automation to a manually inspected session

Risky assumption:

CDP attachment gives me the exact same behavior as a Playwright-launched browser.

It often works well, but it is not the same connection model. When the bug involves cookies, profiles, or proxy context, verify the attached browser before touching the task logic.

Step 1: start a dedicated browser profile

Do not debug this against your daily Chrome profile.

Use a dedicated automation directory:

google-chrome \
  --remote-debugging-port=9222 \
  --user-data-dir=/tmp/pw-cdp-profile \
  --no-first-run

Then log in manually in that browser if the test requires an authenticated state.

Checklist:

  • userDataDir is dedicated to this test.
  • No other Chrome process is using the same directory.
  • The browser was started with the expected remote debugging port.
  • The profile is not your personal default Chrome profile.
  • The profile can be reopened manually and still shows the expected login state.

Validation standard:

The profile must be trusted manually before it is trusted by automation.

If the manual browser is already logged out, Playwright is not the problem yet.

Step 2: attach through CDP and inspect the actual context

Run the smallest possible script before running your real workflow.

import { chromium } from "playwright";

const browser = await chromium.connectOverCDP("http://127.0.0.1:9222");
const context = browser.contexts()[0];

if (!context) {
  throw new Error("No browser context found. Check the CDP endpoint.");
}

const page = context.pages()[0] ?? await context.newPage();

const cookies = await context.cookies();
const storage = await page.evaluate(() => ({
  url: location.href,
  localStorageKeys: Object.keys(localStorage),
  sessionStorageKeys: Object.keys(sessionStorage),
}));

console.log({
  contextCount: browser.contexts().length,
  pageCount: context.pages().length,
  cookieCount: cookies.length,
  storage,
});

Do not skip this.

Checklist:

  • contextCount is what you expected.
  • pageCount is what you expected.
  • The script is using the expected tab or creates a new tab in the expected context.
  • cookieCount is not unexpectedly zero.
  • localStorageKeys match the app you logged into.
  • sessionStorageKeys are not the only place where auth appears to live.
  • Reloading the page does not immediately redirect to login.

If this minimal script fails, the real workflow is irrelevant.

The problem is the attached browser context.

Step 3: check whether cookies are actually the auth source

A common debugging mistake is treating cookies as the whole session.

For many apps, that is not true.

Check each layer:

  • Cookies
  • localStorage
  • IndexedDB
  • sessionStorage
  • service worker state
  • extension state
  • app-specific device or session binding

A useful question is:

Can I explain the login state using only the data that Playwright can see?

Use this snapshot for inspection, not as a blind copy-paste mechanism:

const state = await context.storageState({ indexedDB: true });

console.log({
  cookies: state.cookies.map(cookie => ({
    name: cookie.name,
    domain: cookie.domain,
    path: cookie.path,
    secure: cookie.secure,
    sameSite: cookie.sameSite,
  })),
  origins: state.origins.map(origin => ({
    origin: origin.origin,
    localStorageKeys: origin.localStorage.map(item => item.name),
  })),
});

Notice that this logs metadata, not secret values.

Checklist:

  • Required cookie domains match the current URL.
  • Required cookie paths are not too narrow.
  • Required cookies are not expired.
  • Secure cookies are used over HTTPS.
  • SameSite behavior makes sense for the redirect flow.
  • IndexedDB is checked when the app stores auth there.
  • sessionStorage is considered if login disappears across new tabs or reloads.
  • No auth values are printed into CI logs.

Validation standard:

Do not call it a cookie bug until you know where the app stores auth.

Step 4: verify the proxy from inside the attached session

The page loading is not enough.

The page must load through the expected network identity.

Run an IP check from the same attached page:

await page.goto("https://api.ipify.org?format=json", {
  waitUntil: "domcontentloaded",
});

console.log("public ip:", await page.textContent("body"));

For production systems, replace the public endpoint with your own internal IP echo service.

Checklist:

  • Observed public IP matches the expected proxy group.
  • Observed IP region matches the profile plan.
  • Timezone, locale, and language are consistent with that region.
  • The proxy was configured at the layer you think it was configured at.
  • The CDP-attached browser and the headless worker do not use different proxy paths.
  • Retry logic does not switch to another proxy silently.

Validation standard:

A run is valid only when these match:

  • profile ID
  • browser profile directory
  • CDP endpoint
  • cookie state
  • storage state
  • proxy route
  • IP region
  • execution mode

If the IP is wrong, stop debugging selectors.

Step 5: compare headed, CDP-attached, and headless behavior

When a workflow works manually but fails in automation, compare the environments side by side.

Use this matrix:

Check Headed manual profile CDP-attached Playwright Headless run
Same profile path
Cookie count
localStorage keys
IndexedDB needed
Public IP
Proxy region
Timezone
Locale
Landing URL after reload
Login challenge shown

The goal is not to make every number identical.

The goal is to explain every difference.

Red flags:

  • CDP-attached Playwright has fewer cookies than manual mode.
  • Headless uses a different proxy than headed mode.
  • The same URL redirects differently in each mode.
  • The profile path is different but the run log does not show it.
  • The agent retry opens a fresh context instead of the attached context.

Validation standard:

A headed success does not prove headless readiness. A CDP connection does not prove profile correctness.

Step 6: add stop conditions before an AI agent continues

This is where AI agent debugging differs from script debugging.

A deterministic script often fails loudly.

An agent can adapt and continue.

That is useful for UI variation, but dangerous for identity mismatch.

Before giving an agent a logged-in browser, require environment checks.

Stop the agent when:

  • cookie count drops unexpectedly.
  • The page redirects to login.
  • public IP does not match the expected proxy.
  • IP region changes during retry.
  • timezone and proxy region disagree.
  • localStorage or IndexedDB is empty when it should not be.
  • The agent is not operating in the expected CDP-attached context.
  • The page enters wallet, payment, account settings, deletion, permission, or destructive flows.
  • The agent cannot produce a run log that ties result to profile, proxy, time, and mode.

A good agent run should answer:

  • Which profile did I use?
  • Which browser context did I attach to?
  • Which proxy route did I use?
  • What IP did the page observe?
  • What session state did I verify before acting?
  • Why was I allowed to continue?
  • What would have made me stop?

If the agent cannot answer those, it should not act on a logged-in session.

Step 7: use a small run log for every debug attempt

The log does not need to be fancy.

It just needs to capture the identity of the run.

Example fields:

run_id: 2026-05-30-cdp-auth-debug-001
mode: cdp-attached
cdp_endpoint: http://127.0.0.1:9222
profile_label: qa-us-account-03
user_data_dir: /tmp/pw-cdp-profile
expected_proxy_region: US
observed_public_ip: 203.0.113.10
cookie_count_before: 18
cookie_count_after_reload: 18
local_storage_origins:
  - https://app.example.test
indexeddb_checked: true
landing_url_after_reload: https://app.example.test/dashboard
agent_allowed_to_continue: false
stop_reason: proxy_region_not_verified

This prevents vague debugging notes like:

It worked locally but failed in the agent.

That sentence is not enough.

A better note is:

The CDP-attached run used the expected profile and cookie count, but the observed IP did not match the expected proxy region, so the agent was stopped before account actions.

That is debuggable.

Common causes and first checks

Cause 1: wrong browser was attached

Symptoms:

  • context.cookies() returns fewer cookies than expected.
  • The page is logged out even though another Chrome window is logged in.
  • The CDP port belongs to an older browser process.

First checks:

  • Kill all test Chrome processes.
  • Start one browser with one userDataDir.
  • Reopen the CDP endpoint.
  • Print browser.contexts().length.
  • Print the current URL and cookie count before running actions.

Cause 2: wrong profile directory

Symptoms:

  • Login works in one browser, but CDP sees a clean session.
  • The app asks for first-time setup.
  • The cookie jar is empty.

First checks:

  • Confirm the exact userDataDir used at launch.
  • Check chrome://version manually.
  • Do not use the daily default Chrome profile.
  • Do not let two browser instances share the same directory.

Cause 3: auth is not only stored in cookies

Symptoms:

  • Cookies exist, but the app still logs out.
  • Login survives reload but not a new tab.
  • OAuth callback succeeds but dashboard redirects back to login.

First checks:

  • Inspect localStorage.
  • Inspect IndexedDB.
  • Check sessionStorage.
  • Check service worker and extension dependencies.
  • Verify cookie domain, path, Secure, and SameSite.

Cause 4: proxy context drifted

Symptoms:

  • The page loads but shows another region.
  • Some accounts see different layouts.
  • Verification prompts appear only in automation.
  • Headless tasks produce different results from visible sessions.

First checks:

  • Check public IP inside the attached page.
  • Compare IP, region, timezone, and locale.
  • Verify where the proxy is configured.
  • Disable silent proxy failover during debugging.
  • Record proxy identity with every run.

Cause 5: the AI agent retried from another context

Symptoms:

  • The first attempt fails.
  • The retry succeeds.
  • The result is not reproducible manually.
  • Logs do not show which profile or proxy was used.

First checks:

  • Disable automatic retry.
  • Require pre-run identity checks.
  • Require post-run identity checks.
  • Stop if the retry changes profile, context, proxy, or mode.

Recovery checklist

When the session or proxy context looks wrong, I use this order:

  1. Stop the workflow.
  2. Save screenshot, URL, cookie count, storage keys, and observed IP.
  3. Close the attached browser.
  4. Kill stale Chrome processes.
  5. Restart one browser with the expected userDataDir and CDP port.
  6. Manually confirm login state.
  7. Reattach Playwright.
  8. Re-run the minimal inspection script.
  9. Verify cookies, localStorage, IndexedDB, and sessionStorage assumptions.
  10. Verify proxy, IP region, timezone, and locale.
  11. Run one low-risk page read.
  12. Only then run the real workflow.

Do not recover by blindly copying cookies across unrelated profiles.

That often creates a more confusing state than the original bug.

What a trustworthy run looks like

A Playwright CDP run is trustworthy when you can prove:

  • Correct browser instance
  • Correct CDP endpoint
  • Correct browser profile
  • Expected cookie count
  • Expected storage origins
  • Auth source understood
  • Expected proxy route
  • Expected IP region
  • Expected timezone and locale
  • Same behavior after reload
  • Headed and headless differences explained
  • AI agent stop conditions enabled
  • Run evidence saved

The important shift is this:

The browser opening is not proof.
The page loading is not proof.
The task completing is not proof.

For profile-based automation, the proof is that the task ran from the expected browser identity.

Final note

As soon as you manage more than a few profiles, this debugging problem becomes less about one script and more about operational visibility.

You need to know which browser profile, which session state, which proxy route, which execution mode, and which agent decision produced the result.

A profile-aware browser automation workspace can help keep those relationships visible, but the debugging principle stays the same:

Before asking whether automation worked, verify which identity it worked from.