Code Examples
Four real-shaped examples: a natural-language extraction, a schema-constrained extraction, a markdown read, and branching on the response like a production caller would.
1. Natural Language Extraction
Describe what you want in plain English. No schema required.
curl
curl -X POST https://contrie.com/api/v1/scrape \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $CONTRIE_API_KEY" \
-d '{
"url": "https://example.com/products/wireless-headphones",
"extract": "Get the product name, price, rating, and whether it is in stock"
}'200 OK
{
"success": true,
"data": {
"name": "Wireless Noise-Cancelling Headphones",
"price": 79.99,
"rating": 4.5,
"inStock": true
},
"metadata": {
"extractionMethod": "ai",
"model": "minimax/minimax-m3:free",
"qualityScore": 88,
"grounding": 0.9,
"escalations": 0,
"costUsd": 0,
"trace": [
{ "stage": "heuristic", "detail": "found Product JSON-LD" },
{ "stage": "classify", "detail": "simple" },
{ "stage": "route", "detail": "hedged", "tier": "free" },
{ "stage": "extract", "model": "minimax/minimax-m3:free", "detail": "2140 in / 60 out", "ms": 1340 },
{ "stage": "validate", "detail": "quality 88, grounding 0.9", "quality": 88 }
]
}
}2. JSON Schema Extraction
Pass a schema when downstream code depends on the exact shape. Validation failures cost points against qualityScore.
Node.js
const response = await fetch("https://contrie.com/api/v1/scrape", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${process.env.CONTRIE_API_KEY}`,
},
body: JSON.stringify({
url: "https://example.com/products",
extract: "Get every product on the page",
schema: {
type: "object",
properties: {
products: {
type: "array",
items: {
type: "object",
properties: {
name: { type: "string" },
price: { type: "number" },
inStock: { type: "boolean" },
},
required: ["name", "price"],
},
},
},
required: ["products"],
},
}),
});
const { data, metadata } = await response.json();
// data.products is guaranteed to match the schema when qualityScore >= 70200 OK
{
"success": true,
"data": {
"products": [
{ "name": "Wireless Headphones", "price": 79.99, "inStock": true },
{ "name": "USB-C Cable", "price": 12.5, "inStock": false }
]
},
"metadata": {
"extractionMethod": "ai",
"model": "deepseek/deepseek-v4-pro-0813",
"qualityScore": 96,
"grounding": 1,
"escalations": 0,
"costUsd": 0.0021,
"trace": [
{ "stage": "heuristic", "detail": "no structured data found" },
{ "stage": "classify", "detail": "simple" },
{ "stage": "route", "detail": "budget tier, schema present" },
{ "stage": "extract", "model": "deepseek/deepseek-v4-pro-0813", "detail": "4830 in / 210 out", "ms": 2010 },
{ "stage": "validate", "detail": "schema valid, quality 96", "quality": 96 }
]
}
}3. Read a Page as Markdown
format: "markdown" skips the model entirely — zero cost, and data is null.
curl
curl -X POST https://contrie.com/api/v1/scrape \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $CONTRIE_API_KEY" \
-d '{
"url": "https://news.ycombinator.com",
"format": "markdown"
}'200 OK
{
"success": true,
"data": null,
"markdown": "# Hacker News\n\n1. [Show HN: I built an open-source AI code editor](https://...) (847 points)\n2. ...",
"metadata": {
"extractionMethod": "markdown",
"qualityScore": 100,
"costUsd": 0,
"trace": [
{ "stage": "markdown", "detail": "page reduced to 6.8KB markdown" }
]
}
}The MCP contrie_read tool wraps the same path — see MCP.
4. Branching on the Response
A 200 status doesn't mean the data is good, and a caught error doesn't always mean give up. This is roughly what a production caller should do:
JavaScript
async function extract(url, prompt) {
const res = await fetch("https://contrie.com/api/v1/scrape", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${process.env.CONTRIE_API_KEY}`,
},
body: JSON.stringify({ url, extract: prompt }),
});
const body = await res.json();
if (!res.ok) {
if (body.error?.code === "RENDER_REQUIRED") {
// JS-only page — render it yourself, then call /api/v1/extract
return { needsRender: true };
}
throw new Error(`${body.error.code}: ${body.error.message}`);
}
const { data, metadata } = body;
const lowQuality = metadata.qualityScore < 70;
const ungrounded = metadata.grounding !== undefined && metadata.grounding < 0.8;
if (lowQuality || ungrounded) {
// One retry with a narrower ask, not a blind repeat
const retryRes = await fetch("https://contrie.com/api/v1/scrape", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${process.env.CONTRIE_API_KEY}`,
},
body: JSON.stringify({ url, extract: `Just the: ${prompt}` }),
});
return retryRes.json();
}
return body;
}