Scrape a URL
Fetch a single URL and return it in the formats you ask for. Waits for the result by default, returning a job id if it runs long; set async to always return a job id immediately.
curl --request POST \
--url https://api.hydrafetch.com/v1/web/scrape \
--header 'Content-Type: application/json' \
--header 'X-API-Key: <api-key>' \
--data '
{
"url": "https://example.com",
"maxAge": 302400000,
"cacheOnly": true,
"storeInCache": true,
"preferStructure": true,
"async": true,
"onlyMainContent": true,
"includeTags": [
"article",
"main"
],
"excludeTags": [
".ad",
"#comments"
],
"removeBase64Images": true,
"blockAds": true,
"includeLinks": true,
"renderJs": true,
"waitFor": 15000,
"timeout": 60500,
"location": {
"country": "us",
"languages": [
"en-US",
"en"
]
},
"headers": {},
"formats": [
"markdown"
],
"jsonOptions": {
"schema": {},
"prompt": "Extract the product name, price, and availability."
}
}
'import requests
url = "https://api.hydrafetch.com/v1/web/scrape"
payload = {
"url": "https://example.com",
"maxAge": 302400000,
"cacheOnly": True,
"storeInCache": True,
"preferStructure": True,
"async": True,
"onlyMainContent": True,
"includeTags": ["article", "main"],
"excludeTags": [".ad", "#comments"],
"removeBase64Images": True,
"blockAds": True,
"includeLinks": True,
"renderJs": True,
"waitFor": 15000,
"timeout": 60500,
"location": {
"country": "us",
"languages": ["en-US", "en"]
},
"headers": {},
"formats": ["markdown"],
"jsonOptions": {
"schema": {},
"prompt": "Extract the product name, price, and availability."
}
}
headers = {
"X-API-Key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'X-API-Key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
url: 'https://example.com',
maxAge: 302400000,
cacheOnly: true,
storeInCache: true,
preferStructure: true,
async: true,
onlyMainContent: true,
includeTags: ['article', 'main'],
excludeTags: ['.ad', '#comments'],
removeBase64Images: true,
blockAds: true,
includeLinks: true,
renderJs: true,
waitFor: 15000,
timeout: 60500,
location: {country: 'us', languages: ['en-US', 'en']},
headers: {},
formats: ['markdown'],
jsonOptions: {schema: {}, prompt: 'Extract the product name, price, and availability.'}
})
};
fetch('https://api.hydrafetch.com/v1/web/scrape', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.hydrafetch.com/v1/web/scrape",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'url' => 'https://example.com',
'maxAge' => 302400000,
'cacheOnly' => true,
'storeInCache' => true,
'preferStructure' => true,
'async' => true,
'onlyMainContent' => true,
'includeTags' => [
'article',
'main'
],
'excludeTags' => [
'.ad',
'#comments'
],
'removeBase64Images' => true,
'blockAds' => true,
'includeLinks' => true,
'renderJs' => true,
'waitFor' => 15000,
'timeout' => 60500,
'location' => [
'country' => 'us',
'languages' => [
'en-US',
'en'
]
],
'headers' => [
],
'formats' => [
'markdown'
],
'jsonOptions' => [
'schema' => [
],
'prompt' => 'Extract the product name, price, and availability.'
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-API-Key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.hydrafetch.com/v1/web/scrape"
payload := strings.NewReader("{\n \"url\": \"https://example.com\",\n \"maxAge\": 302400000,\n \"cacheOnly\": true,\n \"storeInCache\": true,\n \"preferStructure\": true,\n \"async\": true,\n \"onlyMainContent\": true,\n \"includeTags\": [\n \"article\",\n \"main\"\n ],\n \"excludeTags\": [\n \".ad\",\n \"#comments\"\n ],\n \"removeBase64Images\": true,\n \"blockAds\": true,\n \"includeLinks\": true,\n \"renderJs\": true,\n \"waitFor\": 15000,\n \"timeout\": 60500,\n \"location\": {\n \"country\": \"us\",\n \"languages\": [\n \"en-US\",\n \"en\"\n ]\n },\n \"headers\": {},\n \"formats\": [\n \"markdown\"\n ],\n \"jsonOptions\": {\n \"schema\": {},\n \"prompt\": \"Extract the product name, price, and availability.\"\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-API-Key", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.hydrafetch.com/v1/web/scrape")
.header("X-API-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"url\": \"https://example.com\",\n \"maxAge\": 302400000,\n \"cacheOnly\": true,\n \"storeInCache\": true,\n \"preferStructure\": true,\n \"async\": true,\n \"onlyMainContent\": true,\n \"includeTags\": [\n \"article\",\n \"main\"\n ],\n \"excludeTags\": [\n \".ad\",\n \"#comments\"\n ],\n \"removeBase64Images\": true,\n \"blockAds\": true,\n \"includeLinks\": true,\n \"renderJs\": true,\n \"waitFor\": 15000,\n \"timeout\": 60500,\n \"location\": {\n \"country\": \"us\",\n \"languages\": [\n \"en-US\",\n \"en\"\n ]\n },\n \"headers\": {},\n \"formats\": [\n \"markdown\"\n ],\n \"jsonOptions\": {\n \"schema\": {},\n \"prompt\": \"Extract the product name, price, and availability.\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.hydrafetch.com/v1/web/scrape")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-API-Key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"url\": \"https://example.com\",\n \"maxAge\": 302400000,\n \"cacheOnly\": true,\n \"storeInCache\": true,\n \"preferStructure\": true,\n \"async\": true,\n \"onlyMainContent\": true,\n \"includeTags\": [\n \"article\",\n \"main\"\n ],\n \"excludeTags\": [\n \".ad\",\n \"#comments\"\n ],\n \"removeBase64Images\": true,\n \"blockAds\": true,\n \"includeLinks\": true,\n \"renderJs\": true,\n \"waitFor\": 15000,\n \"timeout\": 60500,\n \"location\": {\n \"country\": \"us\",\n \"languages\": [\n \"en-US\",\n \"en\"\n ]\n },\n \"headers\": {},\n \"formats\": [\n \"markdown\"\n ],\n \"jsonOptions\": {\n \"schema\": {},\n \"prompt\": \"Extract the product name, price, and availability.\"\n }\n}"
response = http.request(request)
puts response.read_body{
"data": {
"url": "https://example.com",
"finalUrl": "https://example.com/",
"redirected": false,
"status": 200,
"cached": false,
"metadata": {
"title": "Example Domain",
"pageType": "article",
"wordCount": 214,
"description": "A short summary of the page, as published by the page itself.",
"language": "en",
"author": "Jane Doe",
"siteName": "Example Blog",
"publishedTime": "2026-01-05",
"image": "https://example.com/cover.png"
},
"warning": "<string>",
"usage": {
"creditsUsed": 1,
"creditsRemaining": 4999,
"freshness": "fresh"
},
"quality": {
"confidence": 0.94,
"complete": true,
"blocked": false
},
"markdown": "<string>",
"html": "<string>",
"rawHtml": "<string>",
"links": {
"internal": [
"<string>"
],
"external": [
"<string>"
]
},
"structured": {
"entities": [
{
"type": "Product",
"properties": {}
}
],
"jsonLd": [
{}
],
"microdata": [
{}
],
"opengraph": [
{}
],
"rdfa": [
{}
],
"appState": [
"<string>"
]
},
"summary": "<string>",
"json": {}
}
}{
"jobId": "019f3c09-6fae-740f-9257-10c2b6af7f43",
"status": "queued"
}Authorizations
Body
The URL to scrape. Must be http(s).
"https://example.com"
Serve from cache if a capture of this URL is younger than this many milliseconds. Omit for the default 24h window; 0 always fetches fresh. Capped at 7 days.
0 <= x <= 604800000Only serve from cache. If there is no fresh cached copy, return 404 instead of fetching.
Persist the capture for later re-extraction. Default true.
Preserve document structure (headings, lists, tables) over prose density — good for marketing and service pages. Default off.
Return a job id immediately instead of waiting for the result. Poll GET /v1/web/scrape/{id}.
Return only the main content, dropping nav/boilerplate. Default true.
CSS selectors to keep. When set, only matching elements are considered.
50["article", "main"]
CSS selectors to strip before extraction.
50[".ad", "#comments"]
Strip inline base64 images from the output. Default true.
Remove common ad and tracking elements. Default true.
Keep inline links in the markdown. Default false — dropping them is what keeps our output dense. Turn on for reference, API-docs and code pages where cross-references are content.
Force full page rendering for JavaScript-heavy pages. Left to the pipeline when omitted.
Extra milliseconds to let the page settle before capture.
0 <= x <= 30000Overall time budget for the request, in milliseconds.
1000 <= x <= 120000Show child attributes
Show child attributes
Extra request headers to send when fetching the page.
Show child attributes
Show child attributes
What to return. Omit for Markdown only. structured is the page's own data (no LLM, cheapest); summary and json are LLM-backed and cost more.
markdown, html, rawHtml, links, structured, summary, json ["markdown"]
Schema and/or prompt for the json format. One is required when json is requested.
Show child attributes
Show child attributes
Response
The scraped page.
Show child attributes
Show child attributes
curl --request POST \
--url https://api.hydrafetch.com/v1/web/scrape \
--header 'Content-Type: application/json' \
--header 'X-API-Key: <api-key>' \
--data '
{
"url": "https://example.com",
"maxAge": 302400000,
"cacheOnly": true,
"storeInCache": true,
"preferStructure": true,
"async": true,
"onlyMainContent": true,
"includeTags": [
"article",
"main"
],
"excludeTags": [
".ad",
"#comments"
],
"removeBase64Images": true,
"blockAds": true,
"includeLinks": true,
"renderJs": true,
"waitFor": 15000,
"timeout": 60500,
"location": {
"country": "us",
"languages": [
"en-US",
"en"
]
},
"headers": {},
"formats": [
"markdown"
],
"jsonOptions": {
"schema": {},
"prompt": "Extract the product name, price, and availability."
}
}
'import requests
url = "https://api.hydrafetch.com/v1/web/scrape"
payload = {
"url": "https://example.com",
"maxAge": 302400000,
"cacheOnly": True,
"storeInCache": True,
"preferStructure": True,
"async": True,
"onlyMainContent": True,
"includeTags": ["article", "main"],
"excludeTags": [".ad", "#comments"],
"removeBase64Images": True,
"blockAds": True,
"includeLinks": True,
"renderJs": True,
"waitFor": 15000,
"timeout": 60500,
"location": {
"country": "us",
"languages": ["en-US", "en"]
},
"headers": {},
"formats": ["markdown"],
"jsonOptions": {
"schema": {},
"prompt": "Extract the product name, price, and availability."
}
}
headers = {
"X-API-Key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'X-API-Key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
url: 'https://example.com',
maxAge: 302400000,
cacheOnly: true,
storeInCache: true,
preferStructure: true,
async: true,
onlyMainContent: true,
includeTags: ['article', 'main'],
excludeTags: ['.ad', '#comments'],
removeBase64Images: true,
blockAds: true,
includeLinks: true,
renderJs: true,
waitFor: 15000,
timeout: 60500,
location: {country: 'us', languages: ['en-US', 'en']},
headers: {},
formats: ['markdown'],
jsonOptions: {schema: {}, prompt: 'Extract the product name, price, and availability.'}
})
};
fetch('https://api.hydrafetch.com/v1/web/scrape', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.hydrafetch.com/v1/web/scrape",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'url' => 'https://example.com',
'maxAge' => 302400000,
'cacheOnly' => true,
'storeInCache' => true,
'preferStructure' => true,
'async' => true,
'onlyMainContent' => true,
'includeTags' => [
'article',
'main'
],
'excludeTags' => [
'.ad',
'#comments'
],
'removeBase64Images' => true,
'blockAds' => true,
'includeLinks' => true,
'renderJs' => true,
'waitFor' => 15000,
'timeout' => 60500,
'location' => [
'country' => 'us',
'languages' => [
'en-US',
'en'
]
],
'headers' => [
],
'formats' => [
'markdown'
],
'jsonOptions' => [
'schema' => [
],
'prompt' => 'Extract the product name, price, and availability.'
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-API-Key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.hydrafetch.com/v1/web/scrape"
payload := strings.NewReader("{\n \"url\": \"https://example.com\",\n \"maxAge\": 302400000,\n \"cacheOnly\": true,\n \"storeInCache\": true,\n \"preferStructure\": true,\n \"async\": true,\n \"onlyMainContent\": true,\n \"includeTags\": [\n \"article\",\n \"main\"\n ],\n \"excludeTags\": [\n \".ad\",\n \"#comments\"\n ],\n \"removeBase64Images\": true,\n \"blockAds\": true,\n \"includeLinks\": true,\n \"renderJs\": true,\n \"waitFor\": 15000,\n \"timeout\": 60500,\n \"location\": {\n \"country\": \"us\",\n \"languages\": [\n \"en-US\",\n \"en\"\n ]\n },\n \"headers\": {},\n \"formats\": [\n \"markdown\"\n ],\n \"jsonOptions\": {\n \"schema\": {},\n \"prompt\": \"Extract the product name, price, and availability.\"\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-API-Key", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.hydrafetch.com/v1/web/scrape")
.header("X-API-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"url\": \"https://example.com\",\n \"maxAge\": 302400000,\n \"cacheOnly\": true,\n \"storeInCache\": true,\n \"preferStructure\": true,\n \"async\": true,\n \"onlyMainContent\": true,\n \"includeTags\": [\n \"article\",\n \"main\"\n ],\n \"excludeTags\": [\n \".ad\",\n \"#comments\"\n ],\n \"removeBase64Images\": true,\n \"blockAds\": true,\n \"includeLinks\": true,\n \"renderJs\": true,\n \"waitFor\": 15000,\n \"timeout\": 60500,\n \"location\": {\n \"country\": \"us\",\n \"languages\": [\n \"en-US\",\n \"en\"\n ]\n },\n \"headers\": {},\n \"formats\": [\n \"markdown\"\n ],\n \"jsonOptions\": {\n \"schema\": {},\n \"prompt\": \"Extract the product name, price, and availability.\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.hydrafetch.com/v1/web/scrape")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-API-Key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"url\": \"https://example.com\",\n \"maxAge\": 302400000,\n \"cacheOnly\": true,\n \"storeInCache\": true,\n \"preferStructure\": true,\n \"async\": true,\n \"onlyMainContent\": true,\n \"includeTags\": [\n \"article\",\n \"main\"\n ],\n \"excludeTags\": [\n \".ad\",\n \"#comments\"\n ],\n \"removeBase64Images\": true,\n \"blockAds\": true,\n \"includeLinks\": true,\n \"renderJs\": true,\n \"waitFor\": 15000,\n \"timeout\": 60500,\n \"location\": {\n \"country\": \"us\",\n \"languages\": [\n \"en-US\",\n \"en\"\n ]\n },\n \"headers\": {},\n \"formats\": [\n \"markdown\"\n ],\n \"jsonOptions\": {\n \"schema\": {},\n \"prompt\": \"Extract the product name, price, and availability.\"\n }\n}"
response = http.request(request)
puts response.read_body{
"data": {
"url": "https://example.com",
"finalUrl": "https://example.com/",
"redirected": false,
"status": 200,
"cached": false,
"metadata": {
"title": "Example Domain",
"pageType": "article",
"wordCount": 214,
"description": "A short summary of the page, as published by the page itself.",
"language": "en",
"author": "Jane Doe",
"siteName": "Example Blog",
"publishedTime": "2026-01-05",
"image": "https://example.com/cover.png"
},
"warning": "<string>",
"usage": {
"creditsUsed": 1,
"creditsRemaining": 4999,
"freshness": "fresh"
},
"quality": {
"confidence": 0.94,
"complete": true,
"blocked": false
},
"markdown": "<string>",
"html": "<string>",
"rawHtml": "<string>",
"links": {
"internal": [
"<string>"
],
"external": [
"<string>"
]
},
"structured": {
"entities": [
{
"type": "Product",
"properties": {}
}
],
"jsonLd": [
{}
],
"microdata": [
{}
],
"opengraph": [
{}
],
"rdfa": [
{}
],
"appState": [
"<string>"
]
},
"summary": "<string>",
"json": {}
}
}{
"jobId": "019f3c09-6fae-740f-9257-10c2b6af7f43",
"status": "queued"
}