Fetch a URL and receive its summary as text, not JSON-structured data. Pick a length (short, medium, long) or an exact max_words target, choose plain text or markdown output, and set the language (defaults to the page’s own language, any ISO-639-1 code works). Add free-text instructions to steer the focus: what to emphasize, the audience or tone, a question to answer from the page. The response also includes key_points (the bullet form of the summary) and the page title.
The page is fetched through the same stack as Scrape
, so all fetch options (render_js, proxy_type, sessions, cookies, wait_for) work here too.
HTTP Request
Send the parameters as a JSON body. The same parameters are also accepted as query-string parameters on a GET request. Same handler, same billing, same errors.
Parameters
| Parameter | Type | Required | Default | Description |
|---|
url | string | Yes | — | Absolute http(s) URL to fetch. URL-encode it if it has its own query string. |
length | string | No | medium | How long: short is about 1-2 sentences (roughly 60 words), medium about one paragraph (roughly 150 words), long about 3-5 short paragraphs (roughly 400 words). A target the model aims for, not a hard limit. Ignored when max_words is set. |
max_words | integer | No | — | Word target (20-1000) that overrides length. The text is never cut by the API, so treat it as a target, not a hard limit. |
format | string | No | text | Shape of summary: text (plain prose) or markdown (prose with light markdown, short headings and emphasis). The bullet form is always available in key_points. |
language | string | No | page’s own | Language to write the summary in, as a lowercase ISO-639-1 code with optional region (en, es, pt-BR). Omit to use the page’s own language. |
instructions | string | No | — | Extra instructions, max 1000 characters: what to focus on (pricing and delivery), audience or tone (for a 10-year-old), a question to answer from the page (what does it say about refunds?), things to leave out. The summary never invents facts that are not on the page. |
render_js | string | No | auto | false = plain HTTP fetch, true = headless browser rendering, auto = HTTP first, browser only if blocked. You pay for the path that answered. |
proxy_type | string | No | datacenter | datacenter or isp (static-residential exits, higher trust with strict targets, more credits). |
session_id | string | No | generated | Sticky handle (1-64 chars A-Za-z0-9_-): the same value always routes through the same outbound IP. Sessions are per proxy_type. |
cookies | object / string / list | No | — | Cookies to send. HTTP path only. |
user_agent | string | No | — | User-Agent to send. Drives the TLS/header fingerprint. HTTP path only. |
headers | object | No | {} | Extra request headers. Reserved names (Host, Cookie, User-Agent, Authorization, sec-*, …) are rejected. |
method | string | No | GET | HTTP method used against the target: GET or POST. |
body | string | No | — | Request body sent to the target when method is POST. Requires a Content-Type in headers. |
wait_for | string | No | — | Browser path only: CSS selector to wait for before capturing. At most 15 seconds and never past timeout. |
timeout | integer | No | 25 | Total budget in seconds for the whole request, fetch and rendering included (max 27). |
fields | string | No | all | Comma-separated allow-list of data keys to return, e.g. summary,key_points. |
Credits
Fetch credits plus 5 summary credits when a summary is produced:
| Outcome | proxy_type=datacenter | proxy_type=isp |
|---|
| Fetched over plain HTTP, summary produced | 1 + 5 = 6 | 5 + 5 = 10 |
| Rendered in the headless browser, summary produced | 5 + 5 = 10 | 20 + 5 = 25 |
Thin or script-only page (ai_error: empty_page) | fetch credits only | fetch credits only |
Target blocked the request (blocked: true) | 0 | 0 |
The summary surcharge is billed only when summary is actually produced. A page with no readable text (common for script-rendered pages fetched over plain HTTP) returns ai_error: empty_page and bills the fetch only; retry with render_js=true. A blocked target costs 0 credits.
Response
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
| {
"status": true,
"request_id": "0f3c9d2a",
"data": {
"url": "https://en.wikipedia.org/wiki/Web_scraping",
"http_status": 200,
"summary": "El **web scraping** es la extracción automatizada de datos de sitios web… Su legalidad varía según el país…",
"key_points": [
"Extracción automatizada de datos web mediante bots",
"La legalidad depende de la jurisdicción y de los términos del sitio"
],
"language": "es",
"title": "Web scraping - Wikipedia",
"truncated": false,
"ai_error": null,
"blocked": false,
"block_reason": null,
"detected_protection": null,
"render_used": "http",
"credits": 6,
"elapsed_ms": 2994,
"session_id": "b0d1b2b8ee0d0b0e",
"proxy_type": "datacenter"
}
}
|
Response Fields
| Field | Type | Description |
|---|
status | boolean | true when the summary step produced its result; false when data.ai_error is set. |
request_id | string | Unique identifier for the request. |
data.url | string | Final URL after redirects. |
data.http_status | integer | HTTP status the site returned for the final document, never masked. |
data.summary | string | The summary in the requested format and language. null when ai_error is set. |
data.key_points[] | array | 3-7 short takeaways in page order, the bullet form of the summary. Empty when summary is null. |
data.language | string | ISO-639-1 code the summary is written in; null when unknown. |
data.title | string | The page <title>; null when the page has none. |
data.truncated | boolean | true when the page was longer than the model budget and only its first part was summarized. Never about the summary’s own length. |
data.ai_error | string | Set when no summary was produced: blocked, empty_page, llm_timeout, llm_error, invalid_output. null on success. |
data.blocked | boolean | The target served an anti-bot challenge or rejection instead of content. |
data.block_reason | string | Stable slug explaining the block (cloudflare_challenge, captcha, rate_limited, …); null when not blocked. |
data.detected_protection | string | Anti-bot vendor detected on the page (cloudflare, akamai, datadome, perimeterx, incapsula). Informational: filled even when not blocked. |
data.render_used | string | Which path fetched the page: http or browser. |
data.credits | integer | Credits billed for this call (fetch + summary surcharge). |
data.elapsed_ms | integer | Total server-side time in milliseconds, fetch and summary included. |
data.session_id | string | Sticky-session handle used. Reuse it to keep the same outbound IP. |
data.proxy_type | string | Proxy pool this request went out of. |
Error Responses
| Status | Meaning |
|---|
400 | Invalid request: bad URL, out-of-range max_words or timeout, invalid language code, instructions over 1000 characters, or the URL points at a non-public address. |
415 | The URL returned a non-textual document, e.g. image/png |
502 | The target could not be fetched: DNS failure, connection refused, TLS error, timeout. |
503 | Service temporarily unavailable: retry later. |
A failed summary step is not an HTTP error: it returns 200 with status: false, a top-level error carrying the same slug as data.ai_error, and the full fetch metadata so you can decide how to retry (render_js=true, proxy_type=isp).
1
2
3
4
5
6
7
8
9
10
11
12
13
| {
"status": false,
"error": "empty_page",
"data": {
"url": "https://quotes.toscrape.com/js/",
"http_status": 200,
"summary": null,
"key_points": [],
"ai_error": "empty_page",
"render_used": "http",
"credits": 1
}
}
|
Code Examples
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
| import requests
url = "https://ai-web-scraper-api1.p.rapidapi.com/ai-summarize"
payload = {
"url": "https://blog.cloudflare.com/how-cloudflare-runs-more-ai-models-on-fewer-gpus/",
"length": "short",
"format": "markdown"
}
headers = {
"X-RapidAPI-Key": "YOUR_API_KEY",
"X-RapidAPI-Host": "ai-web-scraper-api1.p.rapidapi.com",
"Content-Type": "application/json"
}
response = requests.post(url, headers=headers, json=payload)
data = response.json()["data"]
print(data["title"])
print(data["summary"])
for point in data["key_points"]:
print(f"- {point}")
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| const url = "https://ai-web-scraper-api1.p.rapidapi.com/ai-summarize";
const response = await fetch(url, {
method: "POST",
headers: {
"X-RapidAPI-Key": "YOUR_API_KEY",
"X-RapidAPI-Host": "ai-web-scraper-api1.p.rapidapi.com",
"Content-Type": "application/json",
},
body: JSON.stringify({
url: "https://blog.cloudflare.com/how-cloudflare-runs-more-ai-models-on-fewer-gpus/",
length: "short",
format: "markdown",
}),
});
const { data } = await response.json();
console.log(data.title);
console.log(data.summary);
data.key_points.forEach((point) => console.log(`- ${point}`));
|
1
2
3
4
5
6
7
8
9
| curl -X POST "https://ai-web-scraper-api1.p.rapidapi.com/ai-summarize" \
-H "Content-Type: application/json" \
-H "X-RapidAPI-Key: YOUR_API_KEY" \
-H "X-RapidAPI-Host: ai-web-scraper-api1.p.rapidapi.com" \
-d '{
"url": "https://blog.cloudflare.com/how-cloudflare-runs-more-ai-models-on-fewer-gpus/",
"length": "short",
"format": "markdown"
}'
|
- Scrape
— Fetch any URL and return its content as HTML, markdown, or text
- AI Extract
— Describe the fields you want and get structured JSON back, no selectors needed