Scrape any site — managed browsers, proxies and bot-protection handling, built in.
CrawlOps gives you two ways to collect data from the web behind one account. Use the Browser WebSocket for full Playwright control with a sticky residential session, or the Scrape API to get HTML, Markdown, screenshots or structured JSON from a single POST — with rotating residential proxies and automatic protection-bypass on both. No proxy ops, no headless-browser fleet to babysit.
Your first scrape — in 30 seconds
Create an API key in the dashboard, then POST a URL. Add render_js when the page needs a real browser.
curl -X POST https://crawl.stratifyops.cloud/v1/scrape \
-H "Authorization: Bearer sk_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{ "url": "https://example.com", "render_js": true }'What you can do
Sticky browser sessions
The Browser WebSocket holds the same residential IP for the whole session (~30 min) — ideal for logins, carts and multi-step flows.
Rotating proxy API
Every Scrape API request exits from a fresh residential IP. Built for high-volume, parallel extraction with zero proxy management.
Bypasses protection layers
Cloudflare challenges, Turnstile and advanced bot protection are detected and handled automatically — on both products.
Geotargeting · 195+ countries
Add proxy_country=us (any ISO code) to route requests through a specific country's residential pool.
JS rendering & screenshots
Render SPAs with a real browser, run declarative click/fill scenarios, and capture full-page screenshots.
LLM-ready output
Return clean Markdown or structured JSON via CSS extract rules — drop straight into RAG, analytics or a database.
Which one should I use?
Browser WebSocket
bt_live_… · wss://…/ws
Sticky residential IP- Full Playwright API over WebSocket
- Same IP for the whole session (~30 min)
- Best for logins, carts, multi-step flows
- Concurrency scales by browser token
Scrape API
sk_live_… · POST /v1/scrape
Rotating residential IP- One POST → HTML, Markdown, JSON or screenshot
- Fresh IP per request, no session to manage
- Best for high-volume, parallel extraction
- CSS extract rules + declarative JS scenarios
Rule of thumb: need to act on a page (click, log in, paginate)? Use the Browser WebSocket. Need to fetch data fast and at scale? Use the Scrape API.
Prefer to click, not code?
The Scrape Builder in your dashboard lets you configure a request — JS rendering, proxy country, Cloudflare solving, CSS extract rules — run it live against any URL, and copy the exact API call to drop into your code.
Code examples & API reference
Pick a product and language below. Every snippet is copy-paste ready, with do/don't notes and the full parameter list.
Playwright WebSocket — full browser control.
Browser token → connect Playwright → disconnect when done.
…/ws?browser_token=bt_live_… &browser=chromiumQuery params
browser_tokenreqstring
Browser token (bt_live_…). Create under Dashboard → Browser Tokens.
browser"chromium" | "firefox"
Browser engine for the session. Default: "chromium". When solve_cloudflare is enabled, the session runs on Firefox — connect with firefox.connect().
solve_cloudflareboolean
Enable automatic Cloudflare challenge solving for the session (runs on Firefox). Default: false.
Connect with Playwright
Attach your existing Playwright script to a remote Chromium session.
Create a browser token (bt_live_…) in the dashboard. · Avoid: Do not put proxy credentials in the WebSocket URL — pass proxy in new_context().
import asyncio
from playwright.async_api import async_playwright
BROWSER_TOKEN = "bt_live_YOUR_TOKEN"
async def main():
async with async_playwright() as pw:
browser = await pw.chromium.connect(
f"wss://browser.stratifyops.cloud/ws?browser_token={BROWSER_TOKEN}&browser=chromium"
)
page = await browser.new_page()
await page.goto("https://example.com")
print(await page.title())
await browser.close()
asyncio.run(main())Cloudflare challenge solving
solve_cloudflare=true enables automatic Cloudflare challenge solving server-side.
Set solve_cloudflare=true on the WebSocket URL. · Avoid: Do not disable JavaScript in the context — challenges need a real browser.
import asyncio
from playwright.async_api import async_playwright
TOKEN = "bt_live_YOUR_TOKEN"
async def main():
async with async_playwright() as pw:
browser = await pw.firefox.connect(
f"wss://browser.stratifyops.cloud/ws?browser_token={TOKEN}&solve_cloudflare=true"
)
page = await browser.new_page()
await page.goto(
"https://nopecha.com/demo/cloudflare",
wait_until="networkidle",
)
print(await page.title())
await browser.close()
asyncio.run(main())Advanced bot protection
Advanced bot-protection blocks are detected after load and handled automatically — no extra flags.
Use a normal WebSocket session with firefox. · Avoid: Do not expect instant HTML — bot-protection handling adds a short post-load delay.
import asyncio
from playwright.async_api import async_playwright
TOKEN = "bt_live_YOUR_TOKEN"
async def main():
async with async_playwright() as pw:
browser = await pw.firefox.connect(
f"wss://browser.stratifyops.cloud/ws?browser_token={TOKEN}&browser=firefox"
)
page = await browser.new_page()
await page.goto(
"https://example.com/protected-page",
wait_until="networkidle",
)
print(await page.title())
await browser.close()
asyncio.run(main())Proxy per session
Route traffic through your own proxy via Playwright context options.
Pass proxy: { server: 'http://user:pass@host:port' } in browser.new_context(). · Avoid: Do not embed proxy credentials in the WebSocket connect URL.
import asyncio
from playwright.async_api import async_playwright
TOKEN = "bt_live_YOUR_TOKEN"
PROXY = "http://user:pass@proxy.example.com:10000"
async def main():
async with async_playwright() as pw:
browser = await pw.chromium.connect(
f"wss://browser.stratifyops.cloud/ws?browser_token={TOKEN}&browser=chromium"
)
ctx = await browser.new_context(proxy={"server": PROXY})
page = await ctx.new_page()
await page.goto("https://example.com")
await browser.close()
asyncio.run(main())Multi-step interactions
Log in, paginate, and extract with the full Playwright API.
Use wait_for_selector after actions that trigger navigation. · Avoid: Do not leave browsers connected overnight — close to free worker capacity.
import asyncio
from playwright.async_api import async_playwright
TOKEN = "bt_live_YOUR_TOKEN"
async def main():
async with async_playwright() as pw:
browser = await pw.chromium.connect(
f"wss://browser.stratifyops.cloud/ws?browser_token={TOKEN}&browser=chromium"
)
page = await browser.new_page()
await page.goto("https://example.com/login")
await page.fill("#email", "user@example.com")
await page.fill("#password", "secret")
await page.click('[type="submit"]')
await page.wait_for_selector(".dashboard")
data = await page.evaluate("""() => ({
user: document.querySelector(".user-name")?.innerText,
})""")
await browser.close()
return data
asyncio.run(main())Free tier — API keys and browser tokens included.