Documentation Index
Fetch the complete documentation index at: https://mintlify.com/vercel-labs/agent-browser/llms.txt
Use this file to discover all available pages before exploring further.
Domain Allowlist
The domain allowlist restricts browser navigation and network requests to a set of trusted domains, preventing AI agents from navigating to unexpected sites or exfiltrating data.
Quick Start
# Restrict to a single domain
agent-browser --allowed-domains "example.com" open example.com
# Allow multiple domains (comma-separated)
agent-browser --allowed-domains "example.com,api.example.com" open example.com
# Use wildcards for subdomains
agent-browser --allowed-domains "*.example.com" open app.example.com
# Via environment variable
export AGENT_BROWSER_ALLOWED_DOMAINS="example.com,*.cdn.example.com"
agent-browser open example.com
How It Works
When enabled, the domain allowlist blocks:
- Document navigation - Prevents navigating to non-allowed domains
- Sub-resource requests - Blocks scripts, images, stylesheets, fetch/XHR to non-allowed domains
- WebSocket connections - Prevents WebSocket connections to non-allowed domains
- EventSource connections - Blocks Server-Sent Events to non-allowed domains
- navigator.sendBeacon - Prevents beacon requests to non-allowed domains
Blocked requests are aborted with blockedbyclient error.
Domain Pattern Syntax
Exact Match
# Only allows example.com (not subdomains)
agent-browser --allowed-domains "example.com" open example.com
Allows:
https://example.com
http://example.com
Blocks:
https://www.example.com
https://api.example.com
https://other.com
Wildcard Subdomains
# Allows all subdomains of example.com
agent-browser --allowed-domains "*.example.com" open app.example.com
Allows:
https://app.example.com
https://api.example.com
https://cdn.example.com
https://example.com (bare domain also matches)
Blocks:
Wildcard patterns like *.example.com automatically match the bare domain example.com for convenience.
Multiple Domains
# Allow multiple domains (comma-separated)
agent-browser --allowed-domains "example.com,api.example.com,*.cdn.net" \
open example.com
Allows:
https://example.com
https://api.example.com
https://images.cdn.net
https://assets.cdn.net
Blocks:
Special URLs
Data and Blob URLs
Data URIs and blob URLs are handled specially:
- Sub-resources: Allowed (images, scripts from data: or blob: URLs)
- Navigation: Blocked (cannot navigate to data: or blob: URLs)
This prevents data exfiltration via data: URL navigation while allowing legitimate use of data URIs for images, etc.
About: and Chrome: URLs
Internal browser URLs (about:, chrome:, chrome-extension:) are blocked.
Implementation Details
Route-based Filtering
Domain filtering is implemented via Playwright’s route interception at the browser context level:
export async function installDomainFilter(
context: BrowserContext,
allowedDomains: string[]
): Promise<void> {
if (allowedDomains.length === 0) return;
await context.route('**/*', async (route: Route) => {
const request = route.request();
const urlStr = request.url();
// Check if URL is http(s)
if (!urlStr.startsWith('http://') && !urlStr.startsWith('https://')) {
// Block non-http(s) navigation, allow other resource types
if (request.resourceType() === 'document') {
await route.abort('blockedbyclient');
} else {
await route.continue();
}
return;
}
// Check domain allowlist
let hostname: string;
try {
hostname = new URL(urlStr).hostname.toLowerCase();
} catch {
await route.abort('blockedbyclient');
return;
}
if (isDomainAllowed(hostname, allowedDomains)) {
await route.continue();
} else {
await route.abort('blockedbyclient');
}
});
}
See domain-filter.ts:src/domain-filter.ts:121 for full implementation.
JavaScript Monkey-patching
WebSocket, EventSource, and navigator.sendBeacon are patched via an init script to enforce domain allowlist at the JavaScript API level:
export function buildWebSocketFilterScript(allowedDomains: string[]): string {
const serialized = JSON.stringify(allowedDomains);
return `(function() {
var _allowedDomains = ${serialized};
function _checkUrl(url) {
try {
var parsed = new URL(url);
return _isDomainAllowed(parsed.hostname);
} catch(e) {
return false;
}
}
if (typeof WebSocket !== 'undefined') {
var _OrigWS = WebSocket;
WebSocket = function(url, protocols) {
if (!_checkUrl(url)) {
throw new DOMException(
'WebSocket connection to ' + url + ' blocked by domain allowlist',
'SecurityError'
);
}
return new _OrigWS(url, protocols);
};
// ... EventSource and sendBeacon patches
}
})();
}
See domain-filter.ts:src/domain-filter.ts:33 for full implementation.
Security Note
This JavaScript monkey-patching is a best-effort defense. If page scripts can use eval(), they could theoretically restore the original WebSocket/EventSource implementations. To close this loophole, deny the eval action category in your action policy:
{
"default": "allow",
"deny": ["eval"]
}
Common Patterns
Single Domain Application
# Only allow the main application domain
export AGENT_BROWSER_ALLOWED_DOMAINS="myapp.com,*.myapp.com"
agent-browser open https://myapp.com
Multi-Domain Application with CDN
# Application + CDN + analytics
export AGENT_BROWSER_ALLOWED_DOMAINS="myapp.com,*.myapp.com,cdn.example.net,*.analytics.com"
agent-browser open https://myapp.com
Development Environment
# Allow localhost and staging
export AGENT_BROWSER_ALLOWED_DOMAINS="localhost,127.0.0.1,*.staging.myapp.com"
agent-browser open http://localhost:3000
Best Practices
1. Include CDN Domains
Many applications load resources from CDNs. Include CDN domains in the allowlist:
# Include CDN domains
agent-browser --allowed-domains "myapp.com,*.cloudfront.net,*.cdn.example.com" \
open https://myapp.com
Without CDN domains, the page may fail to load resources (images, scripts, stylesheets).
2. Use Wildcards for Subdomains
Instead of listing all subdomains:
# Good: use wildcard
agent-browser --allowed-domains "*.myapp.com"
# Bad: list all subdomains
agent-browser --allowed-domains "api.myapp.com,cdn.myapp.com,app.myapp.com"
3. Test Before Deploying
Test the domain allowlist in headed mode to identify missing domains:
# Run in headed mode to see blocked requests
agent-browser --headed \
--allowed-domains "myapp.com" \
open https://myapp.com
# Check network requests to identify blocked resources
agent-browser network requests
4. Combine with Action Policy
For maximum security, combine domain allowlist with action policy:
# Restrict both domains and actions
agent-browser \
--allowed-domains "myapp.com,*.myapp.com" \
--action-policy ./policy.json \
open https://myapp.com
With policy.json:
{
"default": "allow",
"deny": ["eval", "download"]
}
Configuration File
Set domain allowlist in agent-browser.json:
{
"allowedDomains": "myapp.com,*.myapp.com,cdn.example.net"
}
Priority order:
- CLI flag
--allowed-domains
- Environment variable
AGENT_BROWSER_ALLOWED_DOMAINS
- Config file
allowedDomains
Environment Variables
| Variable | Description | Example |
|---|
AGENT_BROWSER_ALLOWED_DOMAINS | Comma-separated list of allowed domain patterns | example.com,*.cdn.example.com |
Programmatic API
Install domain filter programmatically:
import { BrowserManager } from 'agent-browser';
import { installDomainFilter, parseDomainList } from 'agent-browser/domain-filter';
const browser = new BrowserManager();
await browser.launch();
const context = await browser.context();
const allowedDomains = parseDomainList('example.com,*.cdn.example.com');
await installDomainFilter(context, allowedDomains);
await browser.navigate('https://example.com');
Helper Functions
import { isDomainAllowed, parseDomainList } from 'agent-browser/domain-filter';
// Parse comma-separated domain list
const domains = parseDomainList('example.com, *.cdn.net');
console.log(domains);
// ['example.com', '*.cdn.net']
// Check if hostname matches allowlist
const allowed = isDomainAllowed('app.example.com', ['*.example.com']);
console.log(allowed); // true
const blocked = isDomainAllowed('other.com', ['*.example.com']);
console.log(blocked); // false
Troubleshooting
Page fails to load resources
Symptom: Page loads but images, styles, or scripts are missing.
Solution: Check network requests to identify blocked domains:
# Run with domain allowlist
agent-browser --allowed-domains "myapp.com" open https://myapp.com
# Check blocked requests
agent-browser network requests
Add missing CDN domains to allowlist:
agent-browser --allowed-domains "myapp.com,*.cdn.example.com" \
open https://myapp.com
WebSocket connection blocked
Symptom: Error in console: WebSocket connection to wss://... blocked by domain allowlist
Solution: Add the WebSocket server domain to allowlist:
agent-browser --allowed-domains "myapp.com,ws.myapp.com" \
open https://myapp.com
Navigation blocked
Symptom: Cannot navigate to a new page after initial load.
Solution: The target domain is not in the allowlist. Add it:
# Allow navigation to both domains
agent-browser --allowed-domains "myapp.com,docs.myapp.com" \
open https://myapp.com
# Or use wildcard
agent-browser --allowed-domains "*.myapp.com" \
open https://myapp.com
See Also