fetch()
Fetch a single URL with anti-bot bypass
4 min read
Crawling a whole site? Use client.crawl() instead — it handles discovery, fetching, and optional extraction in one call. Use fetch() when you only need a single page.
Endpoint
POST /api/v1/organizations/{org_id}/evadr/fetch
Description
Fetch a single URL with automatic anti-bot bypass. Uses a 4-tier escalation strategy: plain HTTP, browser headers, headless Chrome (CDP), and full browser with proxy. Returns HTML and an artifact ID for chaining with extract() or crawl().
Request body
| Field | Type | Required | Default | Description |
|-------|------|----------|---------|-------------|
| url | string | Yes | — | Target URL |
| force_browser | boolean | No | false | Skip HTTP, go straight to Chrome |
| use_proxy | boolean | No | false | Route through proxy pool |
| session_artifact_id | string | No | null | Authenticated session from Fetchyr |
Response
{
"success": true,
"url": "https://example.com",
"status_code": 200,
"tier_used": 2,
"html": "<html>...</html>",
"vendor_detected": null,
"anti_bot_bypassed": false,
"artifact_id": "art-abc123",
"error": null
}
Response fields
| Field | Type | Description |
|-------|------|-------------|
| success | boolean | Whether fetch succeeded |
| url | string | Resolved URL |
| status_code | integer | HTTP status code |
| tier_used | integer | Tier that succeeded (1-4) |
| html | string | Page HTML |
| vendor_detected | string or null | Anti-bot vendor (e.g. "cloudflare") |
| anti_bot_bypassed | boolean | Whether anti-bot was bypassed |
| artifact_id | string | Reusable artifact ID |
| error | string or null | Error message if failed |
4-Tier escalation
| Tier | Method | Use case | |------|--------|----------| | 1 | Plain HTTP | No protection | | 2 | HTTP + browser headers | Basic bot detection | | 3 | Headless Chrome (CDP) | JS challenges | | 4 | Full browser + proxy | IP-based blocking, TLS fingerprint detection |
Examples
Python
from kloakd import Kloakd
client = Kloakd(api_key="sk-live-...", organization_id="your-org-id")
result = client.evadr.fetch("https://example.com")
print(f"Status: {result.status_code}, Tier: {result.tier_used}")
print(f"HTML length: {len(result.html)}")
print(f"Artifact ID: {result.artifact_id}")
TypeScript
import { Kloakd } from 'kloakd-sdk';
const client = new Kloakd({
apiKey: 'sk-live-...',
organizationId: 'your-org-id',
});
const result = await client.evadr.fetch('https://example.com');
console.log(`Status: ${result.statusCode}, Tier: ${result.tierUsed}`);
console.log(`Artifact ID: ${result.artifactId}`);
Go
result, _ := client.Evadr.Fetch(ctx, "https://example.com", nil)
fmt.Printf("Status: %d, Tier: %d\n", result.StatusCode, result.TierUsed)
fmt.Printf("Artifact ID: %s\n", result.ArtifactID)
cURL
curl -X POST https://api.kloakd.dev/api/v1/organizations/$ORG_ID/evadr/fetch \
-H "Authorization: Bearer sk-live-..." \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com"}'
Artifact chaining
The returned artifact_id can be passed to extract() or crawl() to skip re-fetching:
page = client.evadr.fetch("https://example.com")
# Extract structured data — reuses the fetched HTML
data = client.kolektr.page(
"https://example.com",
schema={"title": "css:h1"},
fetch_artifact_id=page.artifact_id,
)
# Or crawl the site — reuses the fetch for the root page
crawl = client.webgrph.crawl(
"https://example.com",
max_depth=2,
session_artifact_id=page.artifact_id,
)
Force browser mode
Skip HTTP tiers and go straight to Chrome:
result = client.evadr.fetch("https://example.com", force_browser=True)
Authenticated fetch
Pass a session from Fetchyr to access pages behind login:
session = client.fetchyr.login(
url="https://example.com/login",
username_selector="#email",
password_selector="#password",
username="user@example.com",
password="pass",
)
result = client.evadr.fetch(
"https://example.com/dashboard",
session_artifact_id=session.artifact_id,
)
Errors
| Status | Error | When |
|--------|-------|------|
| 400 | ValidationError | Invalid URL |
| 401 | AuthenticationError | Missing or invalid API key |
| 403 | ForbiddenError | Org ID mismatch |
| 429 | RateLimitError | Quota exceeded |
| 502 | UpstreamError | Target site unreachable or all tiers failed |
Learn more
- crawl() orchestrator — discover, fetch, and extract an entire site in one call
- Evadr module — tier details, scan, analyze, SSE streaming
- Authenticated scraping guide — login flows with Fetchyr
- Choosing an approach — when to use fetch vs crawl vs extract
