Sticky Sessions
Make two separate /api/v1/scrape calls behave like one continuous session — same exit IP, shared cookie jar — without manually round-tripping cookies yourself.
When You Need This
Prefer a Single Request When You Can
mode: "js" scrape with actions (wait_for + evaluate) gets it in one call — a browser session is already one IP and one cookie jar. Sticky sessions exist for the genuine multi-request case, where the second fetch is a distinct API call to a separate endpoint.How It Works
1. First Request
Pass an advanced.sticky_session handle on your scrape request. AlterLab pins an exit IP to that handle and captures the target's Set-Cookie jar, returning it as captured_cookies in the response.
2. Second Request
Send the follow-up request with the same sticky_session value. The captured cookies are automatically replayed, and the request is routed through the same exit IP on a best-effort basis — you don't pass the cookies back yourself.
3. No Handle = Fully Isolated
A request without sticky_session never sees another session's cookies. Isolation is the default; opting in is explicit.
Request Fields
Both fields live under the advanced object on POST /api/v1/scrape.
| Field | Type | Default | Description |
|---|---|---|---|
| sticky_session | string | null | Session handle. Same value across calls ⇒ same exit IP and shared cookies. 1–128 characters, letters/digits/-/_ only. |
| sticky_session_ttl | integer | 1800 | Lifetime in seconds, 300–7200. Governs how long the captured cookie jar bound to the handle is retained. Ignored unless sticky_session is set. |
Handle Uniqueness
Response Field
| Field | Type | Description |
|---|---|---|
| captured_cookies | object | null | The Set-Cookie jar captured during this scrape. Present only when sticky_session was used. The next call with the same handle replays these automatically — they're surfaced here mainly for visibility and manual replay if you need it. |
Plan Requirements
Growth Plan or Above Required
sticky_session set from an account below that tier receives a 403 with error code STICKY_SESSION_REQUIRES_PLAN. See pricing for current plan tiers.Tutorial: Load Page, Then Fetch Captcha
A common shape for this feature: a page sets a session cookie on load and shows a captcha image, but that image is served from a separate authenticated endpoint — not embedded inline as data the DOM already exposes. Request 1 establishes the session; request 2 fetches the image using that same session.
# Request 1 — load the page. The target sets a session cookie.
curl -X POST https://api.alterlab.io/api/v1/scrape \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://target.example/login",
"advanced": { "sticky_session": "order-4821", "sticky_session_ttl": 900 }
}'
# -> response includes "captured_cookies": { "PHPSESSID": "sess_9f3a" }
# Request 2 — same handle. Cookies + exit IP carry over automatically.
curl -X POST https://api.alterlab.io/api/v1/scrape \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://target.example/captcha.php",
"advanced": { "sticky_session": "order-4821" }
}'
# -> target receives cookies: {"PHPSESSID": "sess_9f3a"}
# Control — no handle at all. Fully isolated, no cookie leak.
curl -X POST https://api.alterlab.io/api/v1/scrape \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "url": "https://target.example/captcha.php" }'
# -> target receives cookies: {}Full Runnable Example
IP vs Cookie Scoping
Exit IP: Spans Hosts
The same handle pins one exit IP for its session, no matter which host you target with it. One handle = one session-worth of exit IP.
Cookie Jar: Scoped Per Host
The captured cookie jar is keyed by target host. Reusing a handle against a different host loads a separate, empty jar — a site-A cookie never replays onto a site-B request, even under the same handle.
Exit IP Window vs Cookie TTL
sticky_session_ttl you set. For a TTL longer than that window, the shared cookie jar keeps working, but the exit IP behind the handle may have rotated. If your flow strictly requires the same IP end-to-end, keep both requests within a few minutes of each other.Best Practices
1. Use a Meaningful, Unique Handle
An order id, customer id, or a fresh UUID per flow all work well. Avoid reusing a static handle across unrelated flows — that would mix unrelated sessions' cookies for the same host.
2. Set a TTL That Matches Your Flow
A short-lived, two-request flow (load page, fetch asset seconds later) needs a modest TTL. Don't default to the maximum 7200 unless your flow genuinely spans that long.
3. Check for a Single-Request Alternative First
If the data you need is reachable within the same page load, a single mode: "js" request with actions is simpler and doesn't require plan-gated access.
Troubleshooting
403 STICKY_SESSION_REQUIRES_PLAN
Your account is below the growth plan. Upgrade to use sticky_session.
captured_cookies is empty or missing on request 2
Confirm both requests use the exact same sticky_session string, target the same host, and that request 2 fires within the TTL window of request 1. If request 1 didn't set any cookies (some pages don't until you interact with them), there's nothing to replay.
Request 2 appears to use a different exit IP
The exit-IP pin holds for the underlying residential session window (typically ~10 minutes), which can be shorter than your sticky_session_ttl. The cookie jar still replays correctly past that window even if the IP has rotated.
// Minimal request/response shape reference
{
"url": "https://target.example/captcha.php",
"advanced": {
"sticky_session": "order-4821",
"sticky_session_ttl": 900
}
}
// Response (abbreviated)
{
"status_code": 200,
"captured_cookies": { "PHPSESSID": "sess_9f3a" }
}