Integration

Use browser.city with Apify (Actors + Crawlers)

Run large-scale crawling in Apify while delegating stealth browsing, extraction, and proxy egress to browser.city.

Apify is great at orchestration (Actors, scheduling, datasets). browser.city is great at stealth browsing + extraction. Pair them when you want:

  • reliable anti-bot handling (Cloudflare / DataDome / PerimeterX class targets)
  • clean markdown output for pipelines
  • predictable infra primitives (sessions, egress, fingerprints)

If you don’t need multi-step interaction, use the Request API and let Apify handle concurrency and storage.

Batch fetch + markdown (Node.js Actor)

main.ts
import { Actor } from "apify";await Actor.init();const input = (await Actor.getInput()) as { urls: string[] };const res = await fetch("https://api.browser.city/v1/requests/batch", {  method: "POST",  headers: { Authorization: `Bearer ${process.env.BROWSERCITY_API_KEY}`, "Content-Type": "application/json" },  body: JSON.stringify({ requests: input.urls.map((url) => ({ url, markdown: true })) }),}).then((r) => r.json());for (const item of res.responses) await Actor.pushData(item);await Actor.exit();

Why this pattern wins:

  • fewer moving parts than driving Playwright inside the Actor
  • better cost/control for simple extraction workloads
  • easier retry logic (retry individual URLs without keeping a browser alive)

Pattern B: Apify runs Playwright, browser.city provides the remote browser

For logins and multi-step flows, create a browser.city session and connect with Playwright.

session.ts
import { chromium } from 'playwright';const { endpoint, token, id } = await fetch('https://api.browser.city/v1/sessions', {  method: 'POST',  headers: { Authorization: `Bearer ${process.env.BROWSERCITY_API_KEY}`, 'Content-Type': 'application/json' },  body: JSON.stringify({ browser: 'chromium' }),}).then((r) => r.json());try {  const browser = await chromium.connect(endpoint, {    headers: { Authorization: `Bearer ${token}` },  });  const page = browser.contexts().at(0)!.pages().at(0)!;  await page.goto('https://example.com');  console.log(await page.title());} finally {  await fetch(`https://api.browser.city/v1/sessions/${id}`, {    method: 'DELETE',    headers: { Authorization: `Bearer ${process.env.BROWSERCITY_API_KEY}` },  });}

From here you can attach your existing Playwright scripts or crawler logic to browser.

Operational tips

  • Store the key as an Apify secret/env var: BROWSERCITY_API_KEY.
  • Use /v1/requests/batch to reduce per-URL overhead when you can.
  • Use egress and fingerprint options when you need consistent geo/device behavior across runs.
[ 06 / 06 ] — Get Started

Give your AI agents the web.

Start for free. No credit card required. Private sessions by default.