AI Web Agents + Antidetect Profiles: Browser-Use CDP Guide (2026)
Last month I watched an AI web agent book a flight. Not a demo — real booking, real airline, real credit card, the whole flow from search to confirmation email. Ninety seconds in? Cloudflare challenge page.
Flight search worked. Seat selection worked. Passenger details — perfect. Then payment page. Wall. I ran the same flow manually in a fresh Chrome profile. Same wall. I'll be honest, I was annoyed. The LLM had done everything right.
Opened chrome://gpu on the agent's browser. WebGL renderer: ANGLE (Unknown, ANGLE (Google, Vulkan 1.3.0, SwiftShader driver)). The standard headless Chromium fingerprint that every bot in the world shares. The agent's LLM was smarter than most humans at filling out forms — but the browser underneath was screaming "I'm automation" through 40+ fingerprint signals the site was checking.
This is the 2026 AI agent problem nobody talks about: your reasoning model can plan complex multi-step tasks, but it's piloting a browser that gets blocked before it can execute step two.
What We're Building With AI Web Agents
By the end of this tutorial, you'll have a working browser-use agent (or similar LLM web agent) that:
- Launches JustBrowser antidetect profiles via REST API
- Connects to those profiles over Chrome DevTools Protocol
- Runs your agent tasks against a browser with genuine 40+ fingerprint spoofing
- Handles profile lifecycle (start, connect, stop) so agents can work across sessions
Your agent code stays the same. We're changing what browser it talks to. The LLM keeps making decisions; the browser stops getting blocked.
Prerequisites
- Python 3.10+ with browser-use installed (
pip install browser-use) - An LLM API key (OpenAI, Anthropic, or compatible)
- JustBrowser ($9.99/mo — one plan) — the REST API is available from day one of the 7-day trial
- Basic familiarity with async Python and browser automation
- At least one antidetect profile created in JustBrowser
If you're coming from Playwright or Puppeteer setups, the Playwright/Puppeteer antidetect guide covers the fingerprint concepts. This tutorial focuses specifically on the agent integration layer.
Step 1: Create Your Agent Profile in JustBrowser
Before any code, create a profile through the JustBrowser desktop app. Each profile stores:
- A complete fingerprint config (canvas, WebGL, fonts, audio, timezone, screen, 40+ parameters)
- Proxy settings (optional — HTTP/HTTPS/SOCKS5)
- Cookies and localStorage from any previous sessions
- A unique profile ID you'll reference via API
For AI agents, pick fingerprints that match common consumer hardware. Intel UHD 620 or 630 for Windows. Apple M2 for Mac. Don't pick workstation GPUs — a Quadro RTX 8000 is unique enough to track. (Learned this the hard way when debugging why my agent kept getting challenged on the same site. Spent two hours blaming the LLM before I realized the fingerprint was basically a neon sign saying "I cost $5,000 and live in a datacenter." Embarrassing.)
We covered fingerprint selection strategy in the WebGL fingerprinting breakdown. Short version: be boring. Boring is invisible.
Note your profile ID from the profile settings panel. You'll need it.
Step 2: Launch the Profile via REST API
JustBrowser's REST API runs locally when the app is open, bound to 127.0.0.1 on port 36542 by default (configurable in the app).
import httpx
import asyncio
API_BASE = "http://127.0.0.1:36542/api/v1"
HEADERS = {"Authorization": f"Bearer {API_TOKEN}"} # token from the app's API/AI tab — pass headers=HEADERS on every request
PROFILE_ID = "your-profile-id-here"
async def launch_profile(profile_id: str) -> dict:
"""Launch an antidetect profile and return connection info."""
async with httpx.AsyncClient() as client:
response = await client.post(
f"{API_BASE}/profiles/{profile_id}/start",
headers=HEADERS,
json={
"headless": False, # headed mode evades detection better
"args": ["--disable-background-timer-throttling"]
}
)
response.raise_for_status()
return response.json()["data"] # includes cdp_url — use profile_data["cdp_url"] as the CDP endpoint
What happens here: we POST to the start endpoint, JustBrowser starts a Chromium instance with your saved fingerprint configuration, and we get back connection details. The cdp_url is a standard CDP WebSocket URL — any framework that speaks Chrome DevTools Protocol can connect.
If you get connection refused, JustBrowser isn't running. The API only works when the app is open. Yeah, I've debugged "network issues" that were just me forgetting to launch the app. More than once.
Step 3: Connect browser-use to the Antidetect Profile
Here's the part that actually matters. browser-use typically launches its own Chromium instance. We override that:
from browser_use import Agent, Browser, BrowserConfig
from langchain_openai import ChatOpenAI
async def create_antidetect_agent():
# Launch the profile
profile_data = await launch_profile(PROFILE_ID)
cdp_url = profile_data["cdp_url"]
# Configure browser-use to connect to existing browser
browser_config = BrowserConfig(
cdp_url=cdp_url, # Connect to our antidetect profile
headless=False
)
browser = Browser(config=browser_config)
# Create the agent with your preferred LLM
llm = ChatOpenAI(model="gpt-4o")
agent = Agent(
task="Your task description here",
llm=llm,
browser=browser
)
return agent, browser
That's it. Seriously — that's the whole integration. browser-use connects to the already-running antidetect browser instead of launching stock Chromium. The LLM makes decisions, the antidetect browser executes them, and sites see a fingerprint that matches real consumer hardware — not SwiftShader-rendered headless automation.
I kept expecting more complexity here. There isn't any.
Step 4: Run Your Agent Task
async def run_agent_task(task: str):
agent, browser = await create_antidetect_agent()
try:
result = await agent.run(task)
return result
finally:
await browser.close()
await stop_profile(PROFILE_ID)
async def stop_profile(profile_id: str):
"""Stop the profile when done."""
async with httpx.AsyncClient() as client:
await client.post(f"{API_BASE}/profiles/{profile_id}/stop", headers=HEADERS)
# Example usage
asyncio.run(run_agent_task(
"Go to amazon.com, search for 'mechanical keyboard', and list the top 3 results with prices"
))
The agent runs against a browser with consistent, realistic fingerprints. Canvas renders the same hash every session. WebGL reports the same renderer. Fonts enumerate in the same order. Unlike stock Chromium where every session is identical to every other bot, antidetect profiles give you genuinely diverse browser identities.
Step 5: Handle Multiple Agents in Parallel
If you're running multiple agents simultaneously, each needs its own profile:
class AgentProfilePool:
def __init__(self, profile_ids: list[str]):
self.available = list(profile_ids)
self.active = {}
async def acquire(self) -> tuple[str, str]:
"""Get an available profile, return (profile_id, cdp_url)."""
if not self.available:
raise RuntimeError("No profiles available — create more in JustBrowser")
profile_id = self.available.pop(0)
async with httpx.AsyncClient() as client:
response = await client.post(
f"{API_BASE}/profiles/{profile_id}/start",
headers=HEADERS,
json={"headless": False}
)
response.raise_for_status()
data = response.json()["data"]
cdp_url = data["cdp_url"]
self.active[profile_id] = cdp_url
return profile_id, cdp_url
async def release(self, profile_id: str):
"""Stop profile and return it to pool."""
if profile_id in self.active:
async with httpx.AsyncClient() as client:
await client.post(f"{API_BASE}/profiles/{profile_id}/stop", headers=HEADERS)
del self.active[profile_id]
self.available.append(profile_id)
# Usage
pool = AgentProfilePool(["profile-1", "profile-2", "profile-3"])
async def run_parallel_agents(tasks: list[str]):
async def run_one(task):
profile_id, cdp_url = await pool.acquire()
try:
browser_config = BrowserConfig(cdp_url=cdp_url, headless=False)
browser = Browser(config=browser_config)
agent = Agent(task=task, llm=ChatOpenAI(model="gpt-4o"), browser=browser)
result = await agent.run()
return result
finally:
await pool.release(profile_id)
results = await asyncio.gather(*[run_one(t) for t in tasks])
return results
Now you can run multiple agents concurrently, each with isolated fingerprints, cookies, and browsing context. One agent getting challenged doesn't compromise others.
Fair warning: each profile is a full Chromium process. Budget ~500MB RAM per browser. Running 10 parallel agents means ~5GB RAM minimum, probably more for heavy SPAs. My laptop started thermal throttling at 8 concurrent profiles — fans sounded like a jet engine, and I'm pretty sure I shortened its lifespan by a month. Don't be me. Plan your infrastructure accordingly, or at least buy a cooling pad first.
Common Errors and How to Fix Them
Error: playwright._impl._errors.Error: Browser has been closed
Cause: The profile crashed or was stopped before the agent finished.
Fix: Check if JustBrowser is still running. If the app closes, all profiles stop. For long-running agents, add a keep-alive ping or wrap operations in try/except to detect and handle profile death gracefully.
Error: Agent completes but site shows CAPTCHA in screenshots
Cause: Fingerprints are working, but something else is triggering detection — usually proxy quality or behavioral signals.
Fix: Check your proxy. Datacenter IPs get flagged instantly on most protected sites. Residential proxies are almost always necessary — and yeah, they're more expensive, no way around it. Also check if your agent is moving too fast. Sites measure time-to-interact, click velocity, scroll patterns. The LLM might be efficient, but that efficiency looks robotic. Add randomized delays in human ranges (200-800ms between actions, occasional longer pauses). I think this is the most underrated part of agent stealth — speed kills.
For ad-related workflows where you need to verify traffic quality, ClickzProtect helps identify fraudulent click patterns — useful when your agents interact with paid media.
Error: httpx.ConnectError: Connection refused
Cause: JustBrowser isn't running or the API port has been changed from the default 36542 in the app's settings.
Fix: Launch JustBrowser. Open the app's API/AI tab and check the actual port and Bearer token. Also verify nothing else is bound to that port, and that the token in your code matches the one shown in the app.
Error: Profile launches but agent sees "fresh session" state
Cause: You're launching a new profile instead of an existing one with warm-up data.
Fix: Create profiles in JustBrowser's GUI first and note their IDs. Fresh profiles with zero history look suspicious — warm them up either manually or using JustBrowser's cookie warm-up engine before running agents. The affiliate multi-account guide covers warm-up strategy in depth.
Error: Agent works locally but fails on server
Cause: You're probably running headless on the server, which is detectable even with antidetect browsers. And if the "server" is a Linux VM, that's the other half of the problem — JustBrowser ships for Windows x64 and macOS (Apple Silicon) only. There's no Linux build to run.
Fix: Keep the browser on a machine that has a real desktop session — a Windows x64 box or an Apple Silicon Mac — and run it headed, with your agent code on that same host talking to the local API. A dedicated always-on Windows machine is the boring answer here, and boring is the theme of this whole post.
# headed mode, on a host with a real display session
await client.post(
f"{API_BASE}/profiles/{profile_id}/start",
json={"headless": False}
)
You lose the tidiness of a headless Linux container. You gain the detection profile of an actual person's computer, which is the trade you came here to make.
Next Steps
You've got AI agents running through antidetect profiles. Here's where to go from here:
Test before production. Run your agent against CreepJS or BrowserLeaks before hitting real targets. If these tests show consistent, realistic fingerprints, you're ready. If they show SwiftShader or inconsistent values, something's misconfigured. The CreepJS testing walkthrough has the details.
Profile warming. Fresh profiles with zero history trigger suspicion. JustBrowser's cookie warm-up engine hits 127 curated sites across 6 categories to build realistic artifacts. Or let agents do a "warm-up task" first — browse Google, scroll through Wikipedia, watch a YouTube video. Five minutes of normal browsing before the real task improves success rates noticeably. Honestly, this feels silly when you're doing it. But it works.
Proxy matching. A profile claiming to be in Seattle shouldn't route through a Frankfurt IP. Geo-match your proxies. Use residential where you can afford it. The ISP proxy setup guide covers configuration.
Multi-agent orchestration. If you're building production agent systems, you'll want proper profile pool management, health checks, and failure handling. Consider integrating with JustAnalytics to track agent success rates and identify which tasks hit detection walls. For email-based agent workflows (account verification, notification handling), JustEmails provides disposable inbox APIs that pair well with antidetect profiles.
The 7-day trial is how you validate the integration — full access, REST API included, nothing held back for a higher tier. After that it's $9.99/month, or $99.99/year, for unlimited profiles. The card goes in at checkout, which I'd normally grumble about, but cancel inside the seven days and you're not charged. One flat price either way, so there's no tier math to do before you start building.
FAQ
Why do AI web agents get blocked so quickly on protected sites?
AI web agents using browser-use or similar frameworks typically launch stock Chromium instances with default fingerprints. Every agent session reports identical WebGL renderer strings, canvas hashes, and navigator properties. Detection services score these signals together — when 500 "different users" share the same SwiftShader GPU signature and zero browsing history, blocks happen within minutes. The LLM driving the agent is invisible to the site; the browser fingerprint is not.
Can I connect browser-use to an antidetect browser instead of stock Chromium?
Yes. browser-use and similar agent frameworks connect via Chrome DevTools Protocol. JustBrowser exposes CDP endpoints for each launched profile through its REST API. You launch a profile, grab the WebSocket URL, and pass it to browser-use as the connection target instead of letting the framework launch its own browser. The agent controls the antidetect browser with genuine fingerprints instead of stock Chromium.
Does this work with Claude computer-use or other LLM agent patterns?
Any agent pattern that controls a browser through Playwright, Puppeteer, or CDP can connect to antidetect profiles. Claude computer-use, OpenAI function-calling agents, LangChain browser tools — they all speak CDP underneath. The antidetect browser handles the fingerprint layer; the LLM handles the decision layer. They're orthogonal concerns that compose cleanly.
What happens to agent sessions when profiles have existing cookies and history?
The agent inherits whatever state exists in the profile — cookies, localStorage, browsing history, logged-in sessions. This is actually useful: you can warm up profiles manually or with JustBrowser's cookie warm-up engine, then let agents operate as "returning users" instead of fresh sessions. Sites trust returning users more than brand-new visitors with zero history.
Try JustBrowser
Native Chromium antidetect browser — not extension-based. Real C++ engine patches at the canvas / WebGL / audio / font / screen layer, so 40+ identity parameters are genuine, not faked. REST API for Playwright, Puppeteer, Selenium. $9.99/month or $99.99/year. 7-day free trial, card required — cancel any time in the seven days and you are not charged. Unlimited profiles.
Get started → · How it differs from Multilogin / GoLogin / AdsPower
Related Posts
Ready to manage multiple accounts?
Seven days free, then $9.99/month — one plan, everything included.