DEV Community

Cover image for My Playwright Proxy Worked, but Login Still Failed
web4browser
web4browser

Posted on

My Playwright Proxy Worked, but Login Still Failed

I used to treat a passing IP check as a green light.

If Playwright showed the expected proxy IP, I assumed the browser environment was ready.

Then a login-dependent flow broke even though the proxy looked correct.

The IP was right.
The country looked right.
The page loaded.
The form submitted.

Then the flow redirected back to login, lost the session after refresh, or landed in a state that clearly was not usable.

The mistake was simple: I was testing the proxy, but the real problem lived in the full browser context.

A proxy check answers one question:

What IP did this request use?

It does not answer the bigger question:

Can this account trust the browser environment behind the request?

That distinction matters when you are using Playwright with persistent profiles, real session state, redirects, and authenticated browser workflows.

The test that passed may be too small

A simple proxy check proves one narrow thing:

The browser, or one request from the browser, can reach an IP check endpoint through the expected exit IP.

That is useful.

But it does not prove the whole browser workflow is consistent.

It does not prove:

  • the persistent profile is the right one;
  • cookies belong to the expected account context;
  • local storage and IndexedDB are still valid;
  • the login redirect chain used the same route;
  • auth subdomains loaded correctly;
  • the final page belongs to the expected account;
  • the session can survive a reload.

That is why “proxy works” and “the authenticated flow works” are not the same test.

A realistic failure scenario

A typical setup may start like this:

const browser = await chromium.launch({
  proxy: {
    server: 'http://proxy.example:8080'
  }
});
Enter fullscreen mode Exit fullscreen mode

Then the script opens an IP check page:

await page.goto('https://api.ipify.org');
Enter fullscreen mode Exit fullscreen mode

The result is correct.

So you assume the environment is fine.

Then the actual browser task starts:

await page.goto('https://example.com/login');
// fill email
// fill password
// submit
Enter fullscreen mode Exit fullscreen mode

The flow breaks after submit, redirect, 2FA, callback, or dashboard loading.

This is the important distinction:

The IP check tested a simple page.

The login-dependent workflow tested the browser context.

Those are not equivalent.

Check 1: Did you test the proxy inside the same context?

Do not test the proxy in one context and run the real workflow in another.

That sounds obvious, but it happens often during debugging.

For example:

  • proxy is tested with curl;
  • the browser task runs in Playwright;
  • proxy is tested in a fresh browser context;
  • the real workflow runs in a persistent profile;
  • proxy is tested in a headed run;
  • the failing task runs in headless mode.

The first check should be:

Did the IP test run inside the exact same browser context that performed the real task?

A better debugging step is to open the IP check page inside the same context before the login step, then save the result into the run report.

If the IP check and the real task do not share the same browser context, you have not tested the environment that actually failed.

Check 2: Is the persistent profile stale?

Persistent profiles are useful because they keep browser state across runs.

They can also become confusing.

A profile may contain:

  • old cookies;
  • expired session data;
  • local storage from a previous login;
  • IndexedDB records;
  • service workers;
  • cached redirects;
  • remembered account hints;
  • previous device state.

The proxy can be correct today while the profile still carries state from a different run.

That is why a clean profile test is useful.

Do not treat the clean profile as the final answer. Treat it as a comparison.

If the flow works in a clean profile but fails in the persistent one, the problem is probably not the proxy alone. It is likely profile state.

In that case, inspect what the persistent profile is carrying before you keep changing proxy settings.

Check 3: Did the flow cross auth subdomains?

Many authenticated workflows are not a single page.

They may move through:

  • the main app domain;
  • an auth subdomain;
  • an identity provider;
  • a challenge page;
  • a callback URL;
  • the final dashboard.

A proxy check on the first domain does not prove that every auth step loaded correctly.

Add request and response logging around the failing part of the flow:

page.on('requestfailed', request => {
  console.log('FAILED:', request.url(), request.failure()?.errorText);
});

page.on('response', response => {
  if (response.status() >= 400) {
    console.log('HTTP', response.status(), response.url());
  }
});
Enter fullscreen mode Exit fullscreen mode

Look for:

  • failed auth-domain requests;
  • 403 responses;
  • 407 proxy authentication errors;
  • callback URLs that never complete;
  • TLS or timeout errors;
  • redirects that land back on the login page.

The goal is not to log everything forever.

The goal is to capture enough evidence to know where the browser workflow broke.

Check 4: Did storage change after submit?

A successful authenticated flow usually writes new browser state.

Depending on the site, that may include:

  • cookies;
  • local storage;
  • IndexedDB;
  • cache;
  • service worker state.

At minimum, compare browser state before and after the flow.

You do not need a complex framework for the first pass. Even a basic cookie count, storage snapshot, and screenshot can tell you whether the browser actually received new state after submit.

If no relevant storage changes after the form is submitted, the browser may not have completed the real auth flow.

That is a different problem from “the proxy is wrong.”

Check 5: Did you verify the final account identity?

Another common mistake is treating URL arrival as success.

For example:

await page.waitForURL('**/dashboard');
Enter fullscreen mode Exit fullscreen mode

That only proves the browser reached a URL that looks like a dashboard.

It does not prove the right account context loaded.

A stronger check is to verify a stable account marker in the UI.

Examples:

  • visible account email;
  • workspace name;
  • organization label;
  • user avatar menu;
  • account ID in page data;
  • dashboard element that only appears after authentication.

The point is simple:

Do not only verify that a page loaded.

Verify which account context loaded.

Check 6: Does the session survive a reload?

After the flow appears successful, reload the page and verify the account marker again.

If the session disappears after reload, the browser did not produce stable state.

Possible causes include:

  • cookies were not written;
  • storage was not persisted;
  • profile path changed between runs;
  • the flow completed in a temporary context;
  • the redirect chain never finished cleanly.

This matters most when you rely on persistent profiles.

A session that only works inside one temporary run is not the same as a reusable browser profile.

Minimal debugging checklist

Before blaming the proxy, check these:

  • Did the IP test run inside the same Playwright context as the real task?
  • Was the same persistent profile used from start to finish?
  • Was this profile previously used with another account or proxy?
  • Did the flow cross multiple auth domains?
  • Were there failed requests during the redirect chain?
  • Did cookies change after submit?
  • Did local storage or IndexedDB change?
  • Did the session survive reload?
  • Did headed and headless runs behave differently?
  • Did the final page show the expected account identity?

This checklist usually finds the gap faster than repeating the same IP test.

What I save in the run report now

For the next failed run, save a small report.

It can be simple:

{
  "run_id": "login-debug-2026-06-08-001",
  "profile_label": "account-a-profile",
  "proxy_label": "us-east-proxy",
  "ip_check_result": "expected-region",
  "login_start_url": "https://example.com/login",
  "final_url": "https://example.com/dashboard",
  "failed_requests": 2,
  "before_cookie_count": 4,
  "after_cookie_count": 12,
  "session_survived_reload": false,
  "account_marker_found": false
}
Enter fullscreen mode Exit fullscreen mode

Avoid saving raw proxy credentials, passwords, tokens, or private account data in logs.

The run report should help you debug the workflow without leaking sensitive information.

When this becomes a team problem

For a solo script, you can sometimes debug this manually.

It gets painful when the script is no longer yours alone.

Someone may reuse the same profile. Someone may change the proxy without updating the profile notes. A session may be created in one environment and reused in another. Screenshots may be missing. Nobody may know which account context the task actually used.

At that point, the issue is no longer just a script bug.

It becomes a workflow problem.

A team should be able to answer:

  • which profile was used;
  • which proxy was attached;
  • what changed during the flow;
  • which account appeared at the end;
  • where the redirect chain failed;
  • whether a human should review the result before retrying.

That does not require turning every script into a large platform.

It does require treating profile, proxy, session state, screenshots, and run logs as one debugging surface instead of scattered local details.

For teams that need this kind of shared debugging surface, a browser profile workspace can make the profile, proxy, session, and run evidence easier to manage together.

Closing

A working proxy is a good start.

It is not a complete browser workflow test.

If Playwright says the proxy works but the login-dependent flow still breaks, zoom out from the IP check.

Look at the full browser context:

  • profile state;
  • redirects;
  • storage;
  • session persistence;
  • final account identity.

The real question is not only whether the browser reached the internet through the expected proxy.

The real question is whether the account can trust the browser environment behind that request.

Top comments (0)