Docs menu
Crawlora Docs
TypeScript Examples
Call Crawlora from server-side TypeScript with environment variables, fetch, timeouts, typed parsing, and bounded retries.
Fetch wrapper with timeout
Uses the real Google search API path at https://api.crawlora.net/api/v1/google/search.
TypeScript fetch
Use environment variables for secrets and keep Crawlora API keys server-side.
const CRAWLORA_API_KEY = process.env.CRAWLORA_API_KEY;
const CRAWLORA_BASE_URL = "https://api.crawlora.net/api/v1";
if (!CRAWLORA_API_KEY) {
throw new Error("Missing CRAWLORA_API_KEY");
}
const body = {
"country": "us",
"keyword": "chatgpt",
"language": "en",
"limit": 10,
"page": 1
};
const controller = new AbortController();
const timeout = setTimeout(() => controller.abort(), 60_000);
try {
const response = await fetch(`${CRAWLORA_BASE_URL}/google/search`, {
method: "POST",
headers: {
"x-api-key": CRAWLORA_API_KEY,
"Content-Type": "application/json"
},
body: JSON.stringify(body),
signal: controller.signal,
});
const payload = await response.json().catch(() => null);
if (!response.ok) {
throw new Error(`Crawlora request failed: ${response.status} ${JSON.stringify(payload)}`);
}
console.log(payload);
} finally {
clearTimeout(timeout);
}Typed response example
Exact response fields vary by endpoint. Confirm field names on the endpoint reference page before depending on them.
Typed response
type CrawloraEnvelope<T> = {
code?: number;
msg?: string;
data?: T;
};
type GoogleSearchResult = {
title?: string;
link?: string;
snippet?: string;
position?: number;
};
type GoogleSearchData = {
result?: GoogleSearchResult[];
};Server-side Next.js route
Keep Crawlora API keys on your server. Browser code should call your backend route.
app/api/search/route.ts
import { NextResponse } from "next/server";
const CRAWLORA_API_KEY = process.env.CRAWLORA_API_KEY;
const CRAWLORA_BASE_URL = "https://api.crawlora.net/api/v1";
export async function POST(request: Request) {
if (!CRAWLORA_API_KEY) {
return NextResponse.json({ error: "Server API key is not configured" }, { status: 500 });
}
const { keyword, country = "us", language = "en" } = await request.json();
if (typeof keyword !== "string" || keyword.trim().length < 2) {
return NextResponse.json({ error: "Keyword is required" }, { status: 400 });
}
const response = await fetch(`${CRAWLORA_BASE_URL}/google/search`, {
method: "POST",
headers: {
"x-api-key": CRAWLORA_API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({ keyword, country, language, limit: 10, page: 1 }),
});
const payload = await response.json().catch(() => null);
if (!response.ok) {
return NextResponse.json({ error: "Crawlora request failed", details: payload }, { status: response.status });
}
return NextResponse.json(payload);
}Retry and backoff
Retry wrapper
async function retryCrawlora(input: RequestInfo, init: RequestInit, attempts = 3) {
for (let attempt = 1; attempt <= attempts; attempt += 1) {
const response = await fetch(input, init);
if (response.ok) return response;
if (![429, 500, 502, 503, 504].includes(response.status) || attempt === attempts) {
throw new Error(`Crawlora request failed: ${response.status} ${await response.text()}`);
}
await new Promise((resolve) => setTimeout(resolve, Math.min(1000 * 2 ** (attempt - 1), 8000)));
}
throw new Error("Retry loop exited unexpectedly");
}Production checklist
- Use process.env.CRAWLORA_API_KEY
- Do not expose keys in browser code
- Use AbortController timeouts
- Parse JSON defensively
- Handle 429 and temporary 5xx
- Log request IDs when available
Responsible public web data workflows
Crawlora is designed for responsible structured public web data workflows. Customers are responsible for using Crawlora in compliance with applicable laws, third-party rights, target-platform rules, and Crawlora terms.
Read Crawlora termsUse TypeScript with endpoint schemas
Open an endpoint reference page to inspect generated request and response schema summaries.