Skip to main content

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

Was this page helpful?