Sessions & Cookies
Sessions & Cookies
Sessions & Cookies
A Voyager session is an authenticated LinkedIn connection backed by your real browser’s cookies. You provide the cookies once; Voyager forwards them on every call, either through the Chrome extension relay (your real Chrome, real IP) or directly from the server over a residential proxy.
Self-healing sessions with the Chrome extension. The extension auto-syncs cookies whenever they change in Chrome, and the server asks the extension to re-sync when a health check fails. Manual intervention is only needed if LinkedIn actually logs you out (password re-entry, suspicious-activity challenge).
Syncing Cookies
Use POST /api/session to sync cookies. If you’re using the Chrome extension, you never have to do this by hand.
Required Cookies
Optional Parameters
Always include userAgent when syncing cookies. LinkedIn compares the User-Agent from the cookie’s origin browser against the requesting browser. Mismatches can trigger session invalidation or redirect loops.
Session Validation
After syncing, Voyager probes LinkedIn (12s non-blocking timeout) and returns the result:
If the probe returns a failure, sessionValid is false and sessionError describes why. The sync itself still succeeds — validation just tells you whether you can expect calls to work.
Checking Session Health
Use GET /api/session/capabilities for a full status readout:
GET /api/health/tenant is a lighter health check that doesn’t probe LinkedIn. Use it for frequent polling. Use /api/session/capabilities when you need to confirm the session is actually working.
Session Lifecycle
Auto-pause discipline
Voyager’s background session watchdog checks /me periodically. A failed check only auto-pauses the user if the response is a clear auth signal — HTTP 401 or 403. Transient 5xx, network errors, and "Relay connection closed" are logged but never pause a user. This keeps your users active across Railway redeploys, LinkedIn upstream blips, and Chrome extension reconnects.
The RiskMonitor tracks real outbound traffic and auto-pauses on sustained trouble signals:
Paused users get HTTP 423 on every request until the cooldown expires or you manually unpause.
Manual reactivation
If a user is paused (e.g. the RiskMonitor tripped, or checkSession observed a real 401), you have two ways to bring them back:
Or simpler: open the Chrome extension and click Export — a successful POST /api/session auto-flips user.status = 'active'.
Cookie Hot-Swap
Re-sync cookies at any time without interrupting in-flight work. Voyager:
- Replaces stored cookies atomically
- Invalidates per-request caches that depend on the old session (CSRF, mailbox URN)
- Probes the new session
- Resumes using the same server process — no restart
If an action is running when the swap lands, it completes against the old cookies, and the next action picks up the new ones.
Session Expiry
LinkedIn cookies typically last 1–3 months but can expire earlier if:
- LinkedIn detects suspicious activity
- You log out from the browser
- LinkedIn forces a password reset
- The IP changes significantly without the extension relaying
Detection paths
- On an outbound call — LinkedIn returns 401/403 → the endpoint surfaces
SESSION_EXPIREDand theRiskMonitortracks the signal. - Background polling —
PollServicechecks messages/invitations periodically; repeated failures emit asession_expiredwebhook. - On sync —
POST /api/sessionvalidates the new cookies immediately and reportssessionValid.
Recovery
- Log in to LinkedIn in your browser (if you were logged out).
- Click Export in the Voyager Chrome extension — that’s it.
- If you’re managing cookies manually, POST them to
/api/sessionas shown at the top of this page.
Export Current Cookies
For debugging, you can read back the cookies Voyager currently holds:
Transport Architecture
The entire REST surface is pure HTTP — no headless browser anywhere on the server (Puppeteer was removed 2026-04-22). Every outbound LinkedIn call goes through one of two tiers:
- Chrome extension relay (preferred) — the request is forwarded over a WebSocket to the user’s real Chrome, which issues the call from the real browser with real cookies and a real residential IP. Result is streamed back.
- Direct HTTP + residential proxy (fallback) — the server issues the call itself using the stored cookies and an IPRoyal residential proxy, identified by the user’s
proxyCountryif set.
Tier 1 is automatic when the extension is connected. Tier 2 is automatic when it isn’t. Callers never need to choose — and per-endpoint retry logic already handles brief transitions between the two (e.g. a Railway redeploy that drops the WebSocket).