Browser Automation APIs: The Complete Developer Guide
Use managed browsers to render dynamic JavaScript, handle persistent sessions, and extract web data without managing headless infrastructure.
Executive Summary
A Browser Automation API is a managed HTTP endpoint that spins up a headless Chromium browser instance, navigates to a URL, executes JavaScript, handles interactions, and returns the rendered result — without you installing a single browser binary. Instead of running npx playwright install and maintaining a fleet of browser processes, you send a POST request with a URL and get back rendered HTML, a screenshot, or structured data.
The short version: If you need to render one JavaScript page a day, run Playwright locally. If you need a thousand pages an hour with stealth, proxies, and CAPTCHA handling, use an API.
Key Takeaways
- A Browser Automation API replaces self-hosted Playwright/Puppeteer infrastructure with a single HTTP endpoint.
- Persistent browser sessions let you reuse a browser context across multiple steps — login, navigate, extract, repeat.
- Stealth mode is not optional. Without it, headless Chrome is trivially detectable by Cloudflare, DataDome, and PerimeterX.
- Stagehand-style natural-language control lets you describe what to do instead of writing CSS selectors.
- Session-based APIs cost less per action than one-shot renders because the browser stays warm.
- The break-even point between self-hosted and API is roughly 50,000 pages per month.
- CAPTCHA solving integrated into the browser flow doubles success rates on protected sites.
1. Problem Statement
You need data from a website that requires JavaScript. Maybe it is a React SPA that ships an empty <div id="root"> and loads content via API calls after hydration. Maybe it is a SaaS dashboard that renders charts client-side. A plain HTTP GET returns nothing useful. You need a real browser.
So you install Playwright. You write a script that launches a browser, navigates to the URL, waits for the right selector, and extracts the content. It works on your laptop. You deploy it to a server.
Then the problems start. The server runs out of memory because each browser instance consumes 200–400 MB of RAM. Cloudflare blocks your requests because headless Chrome has a detectable fingerprint. A site updates its DOM and your selector breaks. A CAPTCHA appears and your script hangs. You need to rotate proxies but your browser library does not support it natively. You scale to ten concurrent pages and your server falls over.
This is the reality of browser automation at any scale beyond a hobby project. The browser itself is not the hard part. The infrastructure around it — stealth patches, proxy management, CAPTCHA solving, session persistence, concurrency control, monitoring — is the hard part. And it is infrastructure that has nothing to do with the data you actually want.
A Browser Automation API exists to abstract that entire layer away. You send a request. You get data back. The API provider handles the browser farm, the stealth patches, the proxy rotation, and the CAPTCHA fallbacks. Your job is to describe what you need, not to keep a Chromium process alive.
2. History & Context
Browser automation started with Selenium in 2004. Jason Huggins built it to automate testing of internal web applications at ThoughtWorks. Selenium WebDriver became the W3C standard. It worked, but it was slow — each command traveled from your test script to a Selenium server to the browser and back.
In 2017, Google released Puppeteer. It spoke directly to Chrome over the Chrome DevTools Protocol (CDP), bypassing the WebDriver layer. Microsoft followed in 2020 with Playwright, adding cross-browser support (Chromium, Firefox, WebKit), auto-waiting, and a unified API across Python, Node.js, Java, and .NET.
Both libraries solved the browser control problem. Neither solved the infrastructure problem. Running Playwright or Puppeteer at scale means provisioning servers with enough RAM to hold dozens of browser processes, patching Chrome to evade bot detection, managing a proxy pool, integrating CAPTCHA solving, and building a queuing system. Managed services such as Ollagraph emerged to offer this as a service.
The 2025–2026 shift has been toward LLM-driven browser control. Stagehand, an open-source project, introduced natural-language browser actions. Ollagraph integrated Stagehand into its API as /v1/stagehand, letting developers control browsers with plain English instructions.
The second major shift is stealth. Cloudflare reported blocking over 100 million bot requests per second in 2024. Anti-bot systems now fingerprint WebDriver flags, navigator properties, GPU rendering quirks, and even the way a browser window is resized. Modern Browser Automation APIs apply dozens of stealth patches to make headless Chrome look like a real user’s browser.
The third shift is session persistence. Early browser automation APIs treated every request as a fresh browser. Modern APIs support persistent sessions where the browser context stays alive across API calls.
3. What Is a Browser Automation API?
A Browser Automation API is an HTTP service that manages headless browser instances on your behalf. You send a request describing what you want the browser to do — navigate to a URL, click a button, extract text, take a screenshot — and the API returns the result.
Definition: A REST or WebSocket endpoint that provisions a headless Chromium (or Firefox/WebKit) instance, executes navigation and interaction commands, and returns rendered output. The API provider manages browser binaries, stealth patches, proxy rotation, CAPTCHA solving, and concurrency. The consumer sends HTTP requests and receives structured responses.
The key distinction from a traditional web scraping API is interactivity. A scraping API fetches a page and returns its content. A Browser Automation API lets you drive the browser — click, type, scroll, wait, extract — across multiple steps, often within a persistent session.
Three Tiers of Browser Automation APIs
- Tier 1 — Render APIs. Send a URL, get back rendered HTML or a screenshot. No interaction, no session. Example: Ollagraph
/v1/render. - Tier 2 — Session APIs. Open a persistent browser session, then issue multiple commands against it. Navigate, click, extract, screenshot — all within the same browser context. Example: Ollagraph
/v1/sessionfamily. - Tier 3 — LLM-Driven APIs. Describe what you want in natural language. The API uses an LLM to interpret the instruction, find the right element, and execute the action. Example: Ollagraph
/v1/stagehandfamily.
4. Architecture: How a Browser Automation API Works
Understanding what happens when you call a Browser Automation API helps you debug failures and optimize performance. Here is the full request path.
Request Flow
Your Code ──▶ API Gateway ──▶ Orchestrator ──▶ Browser Pool ──▶ Proxy Layer ──▶ Target Website
│
Your Code ◀── API Gateway ◀── Response Parser ◀── CDP Commands ◀── Rendered Page ◀────┘
- Step 1 — Authentication. Your request carries an API key. The gateway validates it, checks your credit balance, and applies rate limits.
- Step 2 — Orchestration. The orchestrator selects an available browser instance from the pool. If you requested a new session, it provisions a fresh Chromium process. If you specified an existing session ID, it routes the command to the running browser.
- Step 3 — Browser Execution. The orchestrator sends CDP commands to the browser. For a render request, this means navigating to the URL, waiting for the
networkidleevent, and serializing the DOM. For a script request, it executes your custom JavaScript inside the page context. - Step 4 — Stealth Injection. Before navigation, the orchestrator injects stealth scripts that override detectable headless properties. These patches run before any website JavaScript executes, making the browser appear as a normal Chrome installation.
- Step 5 — Proxy Routing. The request goes through a proxy. Ollagraph selects an IP based on your proxy configuration — datacenter, residential, or sticky. The proxy layer handles rotation, retries, and geotargeting.
- Step 6 — Response Assembly. The rendered DOM, screenshot bytes, or extracted data is serialized and returned as JSON. The browser instance is either recycled for one-shot renders or kept alive for session-based requests.
Session Lifecycle
Session-based APIs maintain a browser context across multiple API calls:
- Create Session —
POST /v1/sessionreturns asession_id. - Navigate —
POST /v1/session/{id}/renderwith a URL loads the page. - Interact —
POST /v1/session/{id}/scriptruns custom JS in the page context. - Extract — Read rendered HTML or take a screenshot.
- Keep Alive — Send periodic keepalive requests to prevent idle timeout.
- Close —
DELETE /v1/session/{id}releases the browser and frees resources.
The session stays alive as long as you send commands within the idle timeout window, typically 30–300 seconds. If the timeout expires, Ollagraph recycles the browser automatically.
Stagehand Architecture
Stagehand adds an LLM layer on top of the browser:
- Create a Stagehand session with your LLM provider.
- Navigate to a URL.
- Send natural-language instructions such as “click the search bar and type ‘laptops’”.
- Extract data with a JSON schema.
The Stagehand layer uses the LLM to generate Playwright commands from your instruction, executes them, and returns the result. This is slower than direct CDP commands but eliminates the need to write selectors.
5. Components & Workflow
Core Components
- Browser Pool. A pre-warmed pool of Chromium processes. The pool maintains a minimum number of idle browsers to serve requests immediately. When demand spikes, the pool scales up by provisioning new containers.
- Stealth Engine. A collection of JavaScript patches applied before any page content loads. Overrides
navigator.webdriver, populatesnavigator.plugins, matches WebGL renderer strings, and sets realistic screen dimensions. - Proxy Manager. Routes browser traffic through IP addresses matching your target: datacenter, residential, or sticky sessions.
- CAPTCHA Solver. Integrated into the browser flow. Intercepts CAPTCHA challenges, solves them, and injects the solution within the same browser session.
- Session Manager. Tracks active browser sessions, idle time, and resource usage.
Typical Workflow
A typical multi-step extraction follows this pattern:
- Create a session with stealth mode and a US residential proxy.
- Navigate to the login page.
- Run a script to fill in credentials and wait for navigation.
- Navigate to the target page and wait for a specific selector.
- Extract the rendered HTML or run a custom script.
- Take a screenshot for verification.
- Close the session.
6. Configuration & Setup
Prerequisites
- An API key from Ollagraph (starts with
osk_). - HTTP client library:
curl,requestsfor Python,axiosorfetchfor Node.js. - Basic understanding of browser concepts: DOM, selectors, network requests.
Getting Started with Ollagraph Browser Automation API
Step 1 — One-shot render request
curl -X POST https://api.ollagraph.com/v1/render \
-H "Authorization: Bearer osk_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com",
"wait_until": "networkidle",
"timeout": 30000
}'
Step 2 — Create a persistent session
curl -X POST https://api.ollagraph.com/v1/session \
-H "Authorization: Bearer osk_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"stealth": true,
"proxy": "residential",
"proxy_region": "us",
"idle_ttl_seconds": 120
}'
Step 3 — Navigate and run custom JavaScript
curl -X POST "https://api.ollagraph.com/v1/session/{session_id}/render" \
-H "Authorization: Bearer osk_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://target-site.com/dashboard",
"wait_until": "networkidle"
}'
curl -X POST "https://api.ollagraph.com/v1/session/{session_id}/script" \
-H "Authorization: Bearer osk_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"script": "document.querySelectorAll(\".product-price\").map(el => el.textContent)"
}'
Step 4 — Close the session
curl -X DELETE "https://api.ollagraph.com/v1/session/{session_id}" \
-H "Authorization: Bearer osk_YOUR_API_KEY"
Configuration Options
| Option | Values | Description |
|---|---|---|
stealth | true, false | Apply anti-detection patches. Always true for production. |
proxy | datacenter, residential, none | Proxy type for request routing. |
proxy_region | us, eu, asia, auto | Geographic region for the proxy IP. |
wait_until | load, domcontentloaded, networkidle | Condition for considering page loaded. |
timeout | milliseconds (default 30000) | Maximum time to wait for page load. |
idle_ttl_seconds | seconds (default 60) | How long a session stays alive without commands. |
7. Code Examples
Python — One-Shot Render
import requests
API_KEY = "osk_YOUR_API_KEY"
BASE_URL = "https://api.ollagraph.com"
response = requests.post(
f"{BASE_URL}/v1/render",
headers={
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json"
},
json={
"url": "https://example.com",
"stealth": True,
"proxy": "residential",
"wait_until": "networkidle",
"timeout": 30000
}
)
data = response.json()
print(f"Rendered {len(data['rendered_html'])} bytes of HTML")
print(f"Final URL: {data['url']}")
Python — Persistent Session with Login
import requests
import time
API_KEY = "osk_YOUR_API_KEY"
BASE_URL = "https://api.ollagraph.com"
# Step 1: Create session
session_resp = requests.post(
f"{BASE_URL}/v1/session",
headers={"Authorization": f"Bearer {API_KEY}"},
json={
"stealth": True,
"proxy": "residential",
"proxy_region": "us",
"idle_ttl_seconds": 120
}
)
session_id = session_resp.json()["session_id"]
# Step 2: Navigate to login page
requests.post(
f"{BASE_URL}/v1/session/{session_id}/render",
headers={"Authorization": f"Bearer {API_KEY}"},
json={"url": "https://target-site.com/login", "wait_until": "networkidle"}
)
# Step 3: Fill login form via custom script
login_script = """
document.querySelector('#username').value = 'myuser';
document.querySelector('#password').value = 'mypassword';
document.querySelector('button[type="submit"]').click();
"""
requests.post(
f"{BASE_URL}/v1/session/{session_id}/script",
headers={"Authorization": f"Bearer {API_KEY}"},
json={"script": login_script}
)
time.sleep(3)
# Step 4: Navigate to target page
requests.post(
f"{BASE_URL}/v1/session/{session_id}/render",
headers={"Authorization": f"Bearer {API_KEY}"},
json={"url": "https://target-site.com/dashboard", "wait_until": "networkidle"}
)
# Step 5: Extract data
extract_script = """
JSON.stringify({
total_revenue: document.querySelector('.revenue-value')?.textContent?.trim(),
active_users: document.querySelector('.user-count')?.textContent?.trim(),
recent_orders: Array.from(document.querySelectorAll('.order-row')).map(row => ({
id: row.querySelector('.order-id')?.textContent?.trim(),
amount: row.querySelector('.order-amount')?.textContent?.trim(),
status: row.querySelector('.order-status')?.textContent?.trim()
}))
});
"""
extract_resp = requests.post(
f"{BASE_URL}/v1/session/{session_id}/script",
headers={"Authorization": f"Bearer {API_KEY}"},
json={"script": extract_script}
)
print(extract_resp.json()["result"])
# Step 6: Close session
requests.delete(f"{BASE_URL}/v1/session/{session_id}")
Node.js — Stagehand Natural Language Control
const API_KEY = "osk_YOUR_API_KEY";
const BASE_URL = "https://api.ollagraph.com";
async function stagehandDemo() {
const createResp = await fetch(`${BASE_URL}/v1/stagehand`, {
method: "POST",
headers: { Authorization: `Bearer ${API_KEY}` },
body: JSON.stringify({
engine: "playwright",
llm_provider: "openai",
model_name: "gpt-4o",
idle_ttl_seconds: 60
})
});
const { session_id } = await createResp.json();
await fetch(`${BASE_URL}/v1/stagehand/${session_id}/goto`, {
method: "POST",
headers: { Authorization: `Bearer ${API_KEY}` },
body: JSON.stringify({ url: "https://example.com/products" })
});
await fetch(`${BASE_URL}/v1/stagehand/${session_id}/act`, {
method: "POST",
headers: { Authorization: `Bearer ${API_KEY}` },
body: JSON.stringify({ instruction: "click the 'Sort by price' dropdown and select 'Low to High'" })
});
const extractResp = await fetch(`${BASE_URL}/v1/stagehand/${session_id}/extract`, {
method: "POST",
headers: { Authorization: `Bearer ${API_KEY}` },
body: JSON.stringify({
instruction: "extract all product names and prices from the current page",
schema: {
type: "object",
properties: {
products: {
type: "array",
items: {
type: "object",
properties: {
name: { type: "string" },
price: { type: "string" }
}
}
}
}
}
})
});
const data = await extractResp.json();
console.log(JSON.stringify(data, null, 2));
await fetch(`${BASE_URL}/v1/stagehand/${session_id}`, { method: "DELETE" });
}
stagehandDemo();
8. Performance & Benchmarks
We tested Ollagraph’s Browser Automation API against a self-hosted Playwright setup to compare latency, success rate, and cost. The test ran 1,000 requests against 50 different JavaScript-heavy websites (SPAs, e-commerce stores, SaaS dashboards) from a single AWS c6i.xlarge instance in us-east-1.
Results
| Metric | Self-Hosted Playwright | Ollagraph Render API | Ollagraph Session API |
|---|---|---|---|
| Median render time | 3.2s | 4.1s | 2.8s (warm session) |
| P95 latency | 8.7s | 6.3s | 4.9s (warm session) |
| Success rate | 72% | 94% | 96% |
| Memory per browser | 320 MB | N/A (managed) | N/A (managed) |
| CAPTCHA bypass rate | 18% | 89% | 91% |
| Stealth detection rate | 64% blocked | 7% blocked | 5% blocked |
Cost Comparison
| Volume | Self-Hosted (monthly) | Ollagraph API (monthly) |
|---|---|---|
| 1,000 renders | $150 (server + proxy) | $5 |
| 10,000 renders | $350 (server + proxy) | $50 |
| 100,000 renders | $1,200 (2 servers + proxy pool) | $500 |
| 1,000,000 renders | $8,000 (cluster + proxy infra) | $5,000 |
Self-hosted costs assume a dedicated server at $150/month, residential proxy pool at $200/month per 50 IPs, and engineering maintenance estimated at 10 hours/month at $100/hour. The break-even point is around 50,000 renders per month.
9. Security Considerations
- API Key Management. Treat your API key like a database password. Store it in environment variables or a secrets manager, never in code. Use different keys for development and production.
- Data in Transit. All API calls use HTTPS. Verify that your provider encrypts data at rest and offers data retention policies.
- Session Hijacking. Persistent browser sessions maintain cookies, authentication tokens, and localStorage. Treat session IDs as sensitive tokens and rotate them after login flows.
- Bot Detection Risks. Consult your legal team regarding web scraping terms of service and compliance (GDPR, hiQ Labs vs. LinkedIn).
- Provider Security. Ollagraph runs each browser in a separate container with no persistent storage between sessions and does not log page content — only metadata.
10. Troubleshooting
Empty or Partial Rendered HTML
- Slow SPA: Increase timeout to 60 seconds. Change
wait_untiltonetworkidle. - Lazy-loaded content: Use the actions parameter to scroll before extraction.
- Login required: Use a session-based approach. Authenticate first, then navigate.
- Anti-bot detection: Enable
stealth: true. Try a residential proxy.
Session Timeout
Send a keepalive request before the idle timeout expires. Set keepalive interval to half the idle_ttl_seconds value.
CAPTCHA Interception
Enable automatic CAPTCHA solving. Reduce request frequency and use residential proxies for aggressive challenges.
Stealth Detection
Switch to a residential proxy. Ensure stealth: true is set. Add delays between requests.
High Latency
Use session-based API to keep the browser warm. Switch to datacenter proxy for faster requests. Block images and fonts using block_resources.
11. Best Practices
- Use sessions for multi-step workflows. Reusing the same browser, cookies, and proxy avoids cold starts and saves 30–40% latency.
- Set realistic timeouts. Start with 30 seconds, increase to 60 for heavy SPAs.
- Implement retry logic with exponential backoff. Retry failed requests with 1s, 3s, 9s backoff (cap at five retries).
- Monitor credit consumption. Log credit cost from response headers.
- Use the minimum viable browser. If you only need rendered HTML, use a render API. If you need structured data, use an extraction API.
- Close sessions explicitly. Use
try/finallyor context managers to ensure cleanup.
12. Common Mistakes
- Treating a browser automation API like a web scraping API. Don’t pay for full DOM rendering when a structured extraction endpoint suffices.
- Not handling CAPTCHAs. Always configure CAPTCHA solving, even if your target seems unprotected.
- Ignoring the idle timeout. Send keepalive requests during long pauses.
- Using datacenter proxies for protected sites. Residential proxies are necessary for Cloudflare and DataDome.
- Scaling too fast. Ramp up request volume gradually to avoid IP-level rate limiting.
- Forgetting to close sessions. Always close sessions in a
finallyblock to avoid concurrency limits.
13. Alternatives & Comparison
| Feature | Self-Hosted Playwright | Browserless | BrowserStack | Ollagraph API |
|---|---|---|---|---|
| Setup time | Days to weeks | Minutes | Minutes | Minutes |
| Stealth mode | Manual patches | Basic | None | Built-in |
| Residential proxies | Self-managed | Limited | No | Yes |
| CAPTCHA solving | External integration | No | No | Built-in |
| Persistent sessions | Yes (self-managed) | Limited | Yes (testing) | Yes |
| LLM-driven control | No | No | No | Stagehand |
| Cost at 10K/month | ~$350 | ~$100 | ~$400 | ~$50 |
| Success rate (JS sites) | ~72% | ~80% | ~75% | ~94% |
- Self-Hosted Playwright: Best for teams with dedicated infrastructure engineering or low-volume automation.
- Browserless: Best for simple rendering and screenshot needs.
- BrowserStack: Best for cross-browser testing, not production data extraction.
- Ollagraph API: Best for production data extraction pipelines, AI agent browser control, and teams avoiding browser infrastructure entirely.
14. Enterprise / Cloud Deployment
- Concurrency limits. Ollagraph’s default is 10 concurrent sessions for starter plans and 100 for enterprise. Implement a queue or semaphore to stay within limits.
- Geographic distribution. Match proxy regions to target sites (US proxies for US sites, EU for EU).
- Webhook-based async processing. Use async endpoints for high-volume jobs to avoid HTTP timeouts.
- Observability. Log request URL, response status, latency, credit cost, and session ID.
- Multi-Tenant Usage. Use separate API keys per team for cost attribution and independent rate limits.
15. FAQs
Q1. What is a Browser Automation API and how is it different from a web scraping API?
A Browser Automation API controls a real browser — navigating pages, clicking buttons, typing text, and extracting data after JavaScript executes. A web scraping API typically fetches raw HTML and returns it without rendering JavaScript.
Q2. Can I use a Browser Automation API to log into websites?
Yes. Session-based APIs are designed for this. You create a session, navigate to the login page, fill in credentials using a custom script, wait for the post-login redirect, and navigate to authenticated pages.
Q3. How do Browser Automation APIs avoid bot detection?
They apply stealth patches before any website JavaScript runs. These patches override navigator.webdriver, populate navigator.plugins, match WebGL renderer strings, and set realistic screen dimensions.
Q4. What is the difference between a render API and a session API?
A render API is a single request-response without state persistence. A session API creates a persistent browser context that preserves cookies, localStorage, and authentication across multiple commands.
Q5. How much does a Browser Automation API cost?
A single render costs roughly $0.005 at volume pricing. At 10,000 renders per month, expect around $50; at 100,000, around $500.
Q6. What happens when a session times out?
The provider closes the browser and frees resources. Send keepalive requests at regular intervals (half the idle timeout value) to prevent this.
Q7. Can I run custom JavaScript in the browser?
Yes. Session-based APIs expose a script endpoint that executes arbitrary JavaScript in the page context via CDP’s Runtime.evaluate.
Q8. Is a Browser Automation API suitable for real-time applications?
Cold renders take 3–5 seconds; warm session renders take 1–3 seconds. For sub-second responses, consider using a structured data API or caching layer.
Q9. How do I handle CAPTCHAs with a Browser Automation API?
Use a provider with integrated CAPTCHA solving that intercepts challenges and injects solutions within the same browser session.
Q10. What is Stagehand and how does it relate to browser automation?
Stagehand is an open-source framework that adds an LLM layer on top of Playwright. Instead of writing CSS selectors, you describe actions in natural language.
16. Conclusion
Browser Automation APIs have matured from a niche convenience into a core piece of web infrastructure. If you are extracting data from JavaScript-heavy websites, automating login workflows, or building AI agents that browse the web, a managed browser API saves you from maintaining stealth patches, proxy management, CAPTCHA solving, and browser scaling.
The decision between self-hosted and API comes down to volume and engineering bandwidth. Below 50,000 renders per month, the API is almost always cheaper and faster to implement. Above that threshold, self-hosted can be more cost-effective if you have the team to maintain it.
Next steps:
- Explore our Browser Session Management API Guide.
- Read Headless Browser API: Automate Browsers at Scale.
- Learn about LLM-Powered Browser Automation.