August 22, 2025
Authentication is one of the most challenging tasks in browser automation. The main reason behind this is that many applications have protective mechanisms both for authentication and to prevent malicious bots, which can lead to unexpected results when executing automation scripts. These may include:
Session cookies expiring quickly or getting invalidated due to backend drift
MFA prompts that occur after a period of uninterrupted success due to risk-based triggers—like a new device or location
Tokens that expire silently due to missing refresh logic or rotation support
So, how can you overcome these challenges? This article helps you understand and implement proven patterns for keeping automated sessions alive and discusses various strategies that help with authenticated browser automation.
Browser Authentication
Let's first understand how different applications handle web authentication. Your browser manages the token that is validated by the application backend to determine the validity of your session. In many cases, depending on your activity in the application, you can implement or configure a session refresh in the browser.
So, how does the authentication and session handling work in a browser?
Typically, the authentication implementation is handled by an identity server or a service, which produces a token(s) for an authentication challenge like verifying username and password. These may even support extended functionality for authentication like multi-factor authentication (MFA) or passwordless login.

In some implementations like in SPA (Single Page Application), the token is directly stored in browser's localStorage or sessionStorage. Otherwise, the token can be used to establish a server session and store it as a Cookie in the browser.
And, after the initial authentication, the browser sends the cookie or the token to the server with each request where it is being verified. Therefore, understanding the underlying authentication mechanism is crucial for efficiently automating the authentication step and maintaining active sessions through proper token refresh.
Now, let's look at the role of Cookies, Web Storage and HTTP Headers for authentication.

Cookies
This is one of the oldest approaches supported by browsers for authentication. When a server sends a response with a Set-Cookie header, the browser stores this internally and automatically sends it as a header in subsequent requests to valid domains
Cookies can be set either server-side (via Set-Cookie headers) or client-side using JavaScript by setting the document.cookie attribute. For security, cookies can include an HTTP Only flag that prevents JavaScript access, protecting against XSS (cross-site scripting) attacks. Cookies also support both fixed expiry times (Expires/Max-Age) and sliding sessions where the server updates expiry based on activity, with the browser automatically enforcing these expiration rules.
Web Storage
When we talk about using web storage for authentication, typically we refer to localStorage
or sessionStorage
in the browser. These storages can store key value pairs up to several megabytes (ranges from 2 - 10MB based on the browser) per origin.
localStorage
is a type of persistent storage in a browser for a defined domain host and lasts until you clear it using JavaScript.sessionStorage
is similar to localStorage but short-lived and scoped to the browser tab. As soon as you close the browser tab, the storage gets cleared.
These two options are commonly used to store JWT tokens in the browser.
HTTP Headers
When the browser makes a request, it needs to send the authentication token or a Cookie to ensure your server recognizes your identity. Either way, the authentication Token or Cookie is sent using HTTP Headers.
For authentication tokens, we typically use Authorization header set via JavaScript. For Cookies, browsers automatically append them to the Cookies header for any authorized domains.
Approaches in Authenticated Browser Automation
There are three industry-accepted approaches to authenticated browser automation. These are:
Cookie Injection
Chrome Context Object
Fresh Login with a Secret Manager
Let's take a look at each approach in detail for better understanding.
Cookie Injection
This is an approach in which you preload the browser context with the same Cookies and client-side tokens a real user would get after logging in. Once the first page is requested, the server sees a fully formed session.
This can be achieved using frameworks like Playwright in a few lines of code:
As shown above, you can import your Cookies from a local JSON file and attach the Cookies to the browser context upon launching a Chromium browser instance. Therefore, all subsequent requests made within the bounded context will use the attached Cookies.
With this approach, you get benefits such as scripts that are library agnostic. You don't need to be locked to a specific automation library. Any library will let you attach Cookies.
However, you have drawbacks such as:
Breaks on one-time-use refresh tokens
Easy for bot detectors to fingerprint as your Cookie appears out of thin air
If the site requires MFA, this will not work
Chrome Context Object
Here, you reuse the entire profile directory (Cookies, localStorage, IndexedDB, service-workers, GPU fingerprints). To the authentication provider, it looks like the same user is coming back every few hours.
This can be achieved with the following Playwright script:
This approach is more reliable than Cookie Injection because it offers:
Fingerprint consistency: Canvas hash, audio context, and WebGL vendor all stay stable, so anti-bot heuristics remain unbothered.
Silent refresh survival: That hidden /auth/refresh iframe that fires every 10 minutes works because the browser stays open long enough.
Reduced MFA fatigue: If a human completes OTP once in headed mode, the session token will persist.
In most cases, this is the most "realistic" approach in terms of similarity to human behavior. But it is usually more complex to maintain and scale.
Note: for this approach, it is important to update the context object after several runs to allow the refreshed token to be saved.
Fresh Login
This is where you login using the username and password extracted from the secret manager every time you interact with the website. Though this is more robust, it is more expensive as it consumes more time and CPU resources.
However, if you choose to adopt this approach, you can implement it using a simple Playwright script:
Common Troubleshooting Steps for Authenticated Browser Automation
Below are some common errors that you might encounter in your authentication flow.
Impossible-traveller and geo-velocity flags
Identity providers such as Okta, Entra ID, and Ping mark these leaps as medium-to-high risk and either challenge with MFA or kill the session outright.
The trigger is usually a CI runner that hops between regions or an IP pool that is not "sticky". To fix this, tie your job to a single region, run behind a residential or dedicated proxy, and keep the same ASN over time. Managed services such as Anchor provide sticky IP addresses to overcome this challenge. If the business demands global fail-over, spin up one profile per region so each identity has a stable geo-history.
Silent 401s after what looked like a perfect Cookie injection
Your jar restored the session Cookie, but the SPA also keeps a short-lived JWT in localStorage and silently swaps it every few minutes through an iframe.
Because the token you shipped with the job is now stale, every XHR call receives a 401 and the app reloads to /login. Inject both the Cookie jar and the localStorage values, or move to a persistent context so the browser handles the refresh itself. Log every response code and fail the build immediately on the first 401 so you discover drift before the downstream workflow corrupts data.
Headless-fingerprint rejection (“Device looks suspicious”, CAPTCHA loops)
Modern bot-detection systems collect multiple browser and device properties to form a unique fingerprint for each visitor. These properties may include graphic card information (via WebGL vendor), audio context signature (audio context hash), system languages, time-zone, and even how fast JavaScript runs.
A minimal Cookie restore cannot help if the browser advertises itself as webdriver true, or if the canvas hash changes between runs. Use a persistent profile so all low-level fingerprints stay identical; launch Chrome with the same major version in your server as you did when capturing the profile; and disable aggressive stealth plug-ins that randomize on each start–they create instability, not stealth.
MFA suddenly appears even though you turned it off months ago
Adaptive authentication systems escalate when they see unusual velocity of requests, new devices, or repeated failed authentications. Once triggered, the provider may enforce MFA on every login attempt until the session or device is trusted again, where you have to:
Let a human complete the challenge once in headed mode.
Persist the refreshed profile, including the new recovery Cookies or device registration so that your bot inherits the "trusted device" status.
Setup alerts and monitoring on any authentication challenge triggered by the bot to respond promptly to prevent prolonged disruptions for automation.
Session dies every N hours on the dot
That pattern indicates a stateless JWT with an explicit exp (expiration time) claim and no refresh rotation.
You can either keep the browser running so the hidden refresh iframe fires, or schedule a fresh-login fallback every time the payload is about to expire (parse the JWT once and you know the deadline). Jobs that run, say, hourly can store the current exp in a cache and short-circuit to a new login five minutes before it lapses.
Advanced authenticated browser automation
If you've already taken the first steps to implement authenticated browser automation and have already created a successful automation, consider implementing the following advanced workflows to ensure better scalability.
E-mail Based MFA
Suppose that once you logged in, you need to provide an OTP to confirm your session and to move forward. This can be automated by implementing a script that connects to your inbox and reads the email from the sender and inserting the OTP sent onto the website:
You can inject the MFA using the function fetchLatestCode
.
SMS-based MFA
To do so, route SMS to a programmable messaging API (Twilio Verify, Vonage). Next, implement a polling service which polls until a code arrives, then fills the form.
Tip: Phone numbers tied to one IP typically encounter fewer "new device" challenges.
Passkey/ WebAuthn
Automating WebAuthn is still evolving. Chrome DevTools Protocol exposes a credential.setVirtualAuthenticator endpoint that lets you register and assert virtual FIDO2 credentials. Expect brittle flows and always keep a manual recovery path.
To learn more about this, check out the Chrome documentation.
Limitations in Authenticated Browser Automation
Even though you implement authenticated browser automation, there's still limitations in doing so. Some of the common limitations include:
Finite tokens: Some SaaS products rotate refresh tokens every few weeks. Your automation will break unless you log in manually (or with a human-in-the-loop job) and commit new credentials.
Behavioral analytics: Vendors track scroll speed, mouse movement entropy, and even CPU timing. Headless runs are detectable. If the project must stay undetected, budget for commercial anti-bot tooling.
Legals & terms: Automating some sites may violate their TOS; check before shipping.
Keep these in mind, and you're in a good spot with authenticated browser automation.
Concluding thoughts
Authenticated browser automation is no longer an overwhelming challenge, but a simple process to implement. When doing so, treat sessions as short-lived secrets, rehearse recovery flows, and log every redirect and header change.
If you need tested tooling that handles authentication profiles, MFA, and rotating proxies out-of-the-box - check out Anchor Browser.