Tutorial13 min read

Scraping Behind a Login: Cookies and Sessions

Short answer

Web scraping with authentication means sending, with every request, whatever the site uses to recognize a signed-in user: usually a session cookie it set when you logged in, sometimes a bearer token or HTTP Basic credentials. Log in once (a form post, an API call or a real browser), keep the cookies in a cookie jar, send them back on each request and keep one IP for the session. When the session ends mid-run, detect it (a redirect to the login page, a 401 or 403, the login form in the HTML), save a checkpoint, log in again once, retry the failed request once, and stop and alert if it fails a second time. Do it only with an account you are entitled to use and within the site's terms. ProxyField residential proxies keep one IP for a logged-in run with sticky sessions of 30 s to 36 h, from $1.95/GB; start with the Easy Trial: 1 GB for $2.95.

residential IPs
412M+
from, traffic never expires
$1.95/GB
Easy Trial
1 GB for $2.95
At a glance
StepWhat your scraper doesTool
1. Log inPost the form (with its CSRF token), call the login API, or log in with a browsercurl, requests, fetch, Playwright
2. Keep the sessionStore every cookie the site sets and send it back on each requestA cookie jar: -c/-b, requests.Session(), fetch-cookie, storage_state
3. Hold one IPOne sticky proxy session per account, for the length of the job-session-<id>-ttl-<seconds> in the proxy username
4. Check every responseLogin redirect, 401/403, login form, a much shorter pageA logged_out() check
5. RecoverCheckpoint, log in again once, retry once, stop on a second failureThe loop below
On this page 9 sections
  1. How websites keep you logged in
  2. What a cookie carries, and what matters for scrapers
  3. Cookie jars: curl, Python and Node.js
  4. Reusing cookies from your own browser
  5. Keep the login state through a proxy
  6. When the session expires mid-run: detect, log in again, retry
  7. Paywalls and members-only content
  8. The legal line
  9. Scraping Behind a Login FAQ

How websites keep you logged in

MechanismWhat the site gives youWhat your scraper sends backTypical sites
Session cookieSet-Cookie: session=... after the login formThe Cookie header on every requestMost classic websites, shops, dashboards
Bearer token (often a JWT)A token in a JSON responseAuthorization: Bearer <token>Single-page apps, mobile and public APIs
HTTP Basic authenticationNothing; the browser asks for a username and passwordAuthorization: Basic <base64 user:pass> on every requestAdmin panels, intranet tools, some feeds
API keyA key from your account settingsA header or query parameter the docs nameOfficial APIs
Single sign-on (OAuth, SAML)Redirects through an identity provider, then a cookie or tokenWhatever the final step issuesBusiness tools, "Sign in with ..." buttons

Find out which one you have before you write code: log in by hand with DevTools open on the Network tab ("Preserve log" on) and look at the login request and the next one. The Python walkthrough of each type is in scraping a website behind a login with Python.

Easy Trial: 1 GB for $2.95.
Try for the price of 1 GB, no subscription, traffic never expires.

Reusing cookies from your own browser

For a quick job on your own account, you can skip the scripted login: log in in your browser, open DevTools > Network, click any request to the site and copy the value of its Cookie request header. Send it as a header from your script:

Shell
curl -s -H "Cookie: session=PASTE_VALUE_HERE" https://example.com/account

Treat that value like your password: anyone who has it is logged in as you until the session ends. It also expires when you log out in the browser or the site ends the session. Use this for your own account only.

Keep the login state through a proxy

Sites tie a session to more than the cookie. A session cookie that arrives from a new IP, especially in another city or country, can be ended or sent to a security check. So for authenticated scraping:

  • Use a sticky session, not per-request rotation. Rotation gives each request a new IP, which looks like the account hopping around the world.
  • One IP per account. If you work with several accounts you are entitled to use, give each one its own sticky session id and keep it.
  • Match the location you normally log in from (country, region or city).
  • Make the session at least as long as the job, and plan for the moments the IP can still change (the table below).

With ProxyField, the sticky session lasts from 30 s to 36 h (ttl from 30 to 129,600 seconds), with presets of 1, 5, 10 and 30 minutes and 1, 3 and 6 hours. The gateway is gate.proxyfield.io:7000, and <login>-country-us-city-new_york in the username asks for an exit IP in New York. Region, session and session time go in the same username: -region-<region>, -session-<id> and -ttl-<seconds>, as in <login>-country-us-region-new_york-city-new_york-session-he9f2qga-ttl-600; every part after the login is optional.

Shell
curl -x gate.proxyfield.io:7000 -U "<login>-country-us-city-new_york-session-acct1-ttl-7200:<password>" -b cookies.txt -c cookies.txt https://example.com/account
When the IP can change during a sticky sessionWhat happensWhat your scraper should do
No ttl in the usernameThe session lasts 20 minutes by defaultSet ttl to the length of the job
The ttl runs outThe next request leaves from a new IPWork in chunks that fit, or check the login after it
The IP sits idle for 120 sIt is replaced with a new IPKeep pauses under 2 minutes, or expect a new IP
The exit node dropsThe gateway retries once with a new session, so the IP may change; a broken connection is not restored, and the client reconnectsReconnect and check the next response for a logout

The IP is held while its exit node is up. Whenever it changes, a careful site may end the login, which is one more reason to check every response, as below. How the two proxy modes differ is in sticky vs rotating proxies; the authentication options of the proxy itself (username and password or an IP allowlist) are in proxy authentication.

When the session expires mid-run: detect, log in again, retry

A logged-out scraper keeps running and collects login pages instead of data. Check every response for one of these signs:

  • a redirect to the login URL, or a final URL that contains /login or /signin;
  • status 401 or 403 from an API;
  • the login form (a password field) or a "Sign in" link in the HTML where your account name used to be;
  • a page much shorter than usual.

The cookie's expiry date is not the end of the session. Expires and Max-Age only tell the client when to delete the cookie. The server keeps its own session and can end it earlier: after a logout, a password change, an idle timeout, an absolute timeout or a security event (OWASP Session Management Cheat Sheet). Editing the date in your cookie jar changes nothing on the server, so don't do it. If the site issues a refresh token (common with bearer tokens), use its refresh flow instead of a full login.

What to do when a sign appears:

  1. Stop and checkpoint. Save the last record you processed, so the run can resume there.
  2. Log in again once, through the normal login flow, and keep the new cookies in the same jar.
  3. Retry the failed request once. Retry only reads (GET). Don't repeat an action that changes something, such as a form submission or an order, unless you can check whether it already went through.
  4. Stop and alert on a second failure. A failed re-login usually means a wrong password, a locked account or a new check.
  5. Stop for a person on MFA or a CAPTCHA. A second factor, a CAPTCHA or a consent screen needs a human; don't try to get past it.

In Python with requests:

Python
import json, os, re, requests

BASE = "https://example.com"
PROXY = "http://<login>-country-us-city-new_york-session-acct1-ttl-7200:<password>@gate.proxyfield.io:7000"
CHECKPOINT = "checkpoint.json"

class SessionLost(Exception):
    pass

def logged_out(r):
    return ("/login" in r.url or r.status_code in (401, 403)
            or 'type="password"' in r.text)

def login(s):
    html = s.get(f"{BASE}/login", timeout=30).text
    token = re.search(r'name="csrf_token" value="([^"]+)"', html).group(1)
    r = s.post(f"{BASE}/login", timeout=30, data={"csrf_token": token,
               "username": os.environ["SITE_USER"], "password": os.environ["SITE_PASS"]})
    if logged_out(r):
        raise SessionLost("login failed: check the password, or a second factor or check page")

def get(s, url):
    r = s.get(url, timeout=30)
    if not logged_out(r):
        return r
    login(s)                      # the session ended: log in once
    r = s.get(url, timeout=30)    # and retry this request once
    if logged_out(r):
        raise SessionLost(url)    # second failure: stop and alert
    return r

s = requests.Session()
s.proxies = {"http": PROXY, "https": PROXY}
start = json.load(open(CHECKPOINT))["next"] if os.path.exists(CHECKPOINT) else 1
login(s)
for page in range(start, 21):
    html = get(s, f"{BASE}/items?page={page}").text
    # ... parse and store html ...
    json.dump({"next": page + 1}, open(CHECKPOINT, "w"))   # resume point

We ran it on 2026-10-27, without the proxy, against a test server that ends each session after 5 requests although its cookie says Max-Age=3600. The loop logged in 5 times (once at the start, then 4 times after the server ended the session) and collected all 20 pages, and the checkpoint ended at page 21. With a wrong password it stopped at once with SessionLost: login failed. Add the fourth sign (a page much shorter than usual) once you know the normal size of your pages.

Log in again only when a sign appears, not at the start of every request or run. Frequent logins from a script are more likely to trigger security checks, emails to the account owner or lockouts than a session that is reused calmly.

Paywalls and members-only content

A paywall is a login with a subscription behind it. Scraping articles you pay for, for your own reading or analysis, is a different matter from republishing them: the content is still protected by copyright (see is web scraping legal?), and subscription terms usually forbid automated downloading and sharing. Don't get around a paywall you haven't paid for; tricks that hide the paywall without logging in still mean taking content the publisher only sells. If you need news or members-only data at scale, ask the publisher about a license or an official feed.

Scraping Behind a Login FAQ

How does web scraping with authentication work?

ProxyField sticky sessions keep one IP for 30 s to 36 h for a logged-in run (residential proxies start at $1.95/GB), and the scrape itself follows the browser: log in once with a form post, an API call or a real browser, keep the cookies or token it returns, and send them with every request. Check each response for signs of a logout and log in again when needed. Use only accounts you are entitled to and stay within the site's terms.

How do I keep a scraper logged in with session cookies, and what should it do when those cookies expire mid-run?

Keep the cookies in one jar (requests.Session(), curl's -c/-b files or a Playwright state file) and send them with every request from one sticky IP. Check each response for a login redirect, a 401 or 403, or the login form; when one appears, save a checkpoint, log in again once, retry the failed request once, and stop and alert if it fails again. On a second factor or a CAPTCHA, stop for a person.

How do I manage cookies when scraping?

Use your HTTP client's cookie jar instead of handling cookies by hand: requests.Session in Python, -c and -b files in curl, fetch-cookie in Node.js, or a browser context in Playwright. Save the jar between runs if the login should survive, keep one jar per account, and clear it when you want a fresh visitor.

Can I scrape content behind a login or paywall?

Only with an account you are entitled to use, and within the site's terms, which often forbid automated access for logged-in users. Content behind a paywall is usually still under copyright, so scraping your own subscription for personal analysis is different from republishing it, and getting around a paywall you haven't paid for is not allowed.

How do I scrape pages that require login with curl?

Load the login page with -c cookies.txt to get the first cookie and the CSRF token, post the form with -b cookies.txt -c cookies.txt -d "field=value&...", then request the protected pages with -b cookies.txt. For HTTP Basic authentication, curl -u user:pass URL is enough.

How do you handle cookies when web scraping with cURL?

Write cookies with -c file and send them with -b file; use both on the same call to keep the file up to date. You can also send a cookie directly with -b "name=value" or -H "Cookie: name=value", and the file keeps HttpOnly cookies on lines that start with #HttpOnly_.

How can I perform Node.js scraping from websites that use authentication or cookies?

Wrap fetch with fetch-cookie (3.2.0) so cookies persist between calls, post the login form or call the login API, and reuse the same wrapped fetch for the protected pages. For token logins, send Authorization: Bearer <token>; for logins that need a browser, log in with Playwright and save its storage state.

What happens when my cookies expire?

The site treats your next request as a logged-out visitor: you get redirected to the login page, receive a 401 or 403 from an API, or see public content instead of your account. Detect it in your scraper and log in again, or refresh the token if the site gives you a refresh token.

Is a cookie's expiry date the real end of a login session?

No. Expires and Max-Age only tell the client when to delete the cookie; the server can end the session earlier after a logout, a password change, an idle or absolute timeout, or a security event. Changing the date in your cookie jar does not bring the session back, so detect the logout and log in again.

What are web cookies?

Small name and value pairs that a website asks your browser or HTTP client to store and send back on later requests. Sites use them to keep you logged in, remember settings and cookie-banner choices, and measure visits.

Show 2 more questionsShow fewer questions

Should you get around login walls when scraping?

No. A login wall is the site saying the content is not public; getting past it without an account you are entitled to use can break the site's terms and, in some cases, computer-misuse law. Scrape the public pages, log in with your own account within the terms, or ask the site for access or a license.

Do I need sticky sessions to stay logged in while scraping?

Usually yes, if you scrape through proxies: a logged-in session that changes IP on every request can be ended or flagged by the site. Keep one sticky IP per account for the length of the job, in the location you normally log in from; with ProxyField an idle IP is replaced after 120 s, so keep pauses shorter or check the login after them.

Easy Trial: 1 GB for $2.95.

Try for the price of 1 GB, no subscription, traffic never expires.