Ghost Gateway avatar

Ghost Gateway

Pricing

from $30.00 / 1,000 browser minutes

Go to Apify Store
Ghost Gateway

Ghost Gateway

Pricing

from $30.00 / 1,000 browser minutes

Rating

0.0

(0)

Developer

Yann Feunteun

Yann Feunteun

Maintained by Community

Actor stats

0

Bookmarked

1

Total users

0

Monthly active users

2 days ago

Last modified

Categories

Share

One URL that hands you an isolated, stealth Chromium over the Chrome DevTools Protocol.

Ghost Gateway is a standby Actor: it is always addressable at a single HTTPS endpoint, and each client connection gets its own browser. The gateway itself runs no browser — it allocates one in a separate Actor run, fetches that browser's real CDP endpoint, and splices the websocket through to you. You drive it with any CDP client: Playwright, Puppeteer, chrome-remote-interface, or raw websocket.

Browsers are billed per session and per minute held, so an idle integration costs nothing.

Quick start

Every request needs your Apify API token.

GATEWAY=https://<username>--ghost-gateway.apify.actor
# 1. mint a session
curl -X POST "$GATEWAY/v1/sessions" \
-H "authorization: Bearer $APIFY_TOKEN" \
-H 'content-type: application/json' -d '{}'
# -> {"session":"7bd58f05-…","rev":0}
# 2. get a browser and its CDP websocket
curl "$GATEWAY/json/version" -H "authorization: Bearer $APIFY_TOKEN"
# -> {"Browser":"Chrome/149…","webSocketDebuggerUrl":"wss://…/devtools/browser/…"}

Then connect with your CDP client of choice:

import { chromium } from 'playwright';
const browser = await chromium.connectOverCDP(webSocketDebuggerUrl);
const page = await browser.newPage();
await page.goto('https://example.com');
console.log(await page.title());
await browser.close(); // releasing the connection releases the browser

Closing the websocket releases the browser and stops the per-minute charge.

Sessions

A session is durable identity — cookies, storage, and a pinned proxy exit — that outlives any one browser. Allocate a browser against a session, drive it, release it, and allocate another later: the second browser resumes the first one's identity. A session is not itself a billing entity; only live browsers are.

RouteMethodPurpose
/v1/sessionsPOSTMint a session. Returns {session, rev}.
/v1/sessions/:sessionGETSnapshot of the session's stored state.
/v1/sessions/:session/commitPOSTCommit cookies/storage back into the session.
/v1/sessions/:session/browserPOSTAllocate a live browser for the session.
/v1/sessions/:session/proxyGETRead the session's current proxy lease.
/v1/sessions/:session/proxy/acquirePOSTTake a proxy lease.
/v1/sessions/:session/proxy/rotatePOSTRotate to a new exit IP.
/v1/sessions/:session/mutation-leasePOSTTake a write lease, so concurrent writers don't clobber each other.
/v1/sessions/:session/mutation-lease/renewPOSTRenew a held write lease.
/v1/sessions/:session/mutation-lease/releasePOSTRelease a write lease.
/json/version, /json/listGETCDP discovery. webSocketDebuggerUrl points back at the gateway.

Session ids are scoped to the caller — you only ever see your own.

Geography

Browsers egress through residential proxies. A session's exit country is pinned when its proxy lease is taken, and the browser's persona is made to agree with it: Accept-Language, the page's language list, Intl locale, and timezone all match the exit rather than contradicting it.

Not every country is available; an unsupported one is refused at allocation rather than silently served from somewhere else.

Notes

  • Cold starts. With no warm pool configured, the first browser of a session waits for a fresh browser Actor to start. Expect tens of seconds. Subsequent allocations against a warm gateway are much faster.
  • Timeouts. Idle sessions and unclaimed browsers are reaped automatically, so a client that disappears does not leave a browser billing.
  • Errors. 401 means no or invalid token. 404 no_session means the session id was never minted, or not by you. 402 means a browser was allocated but could not be charged, and was released rather than handed over.