Extract JSON-LD
Most pages already carry a machine-readable summary of themselves buried in a script tag, and almost nothing reads it except search crawlers. This endpoint fetches a page and hands you back every JSON-LD block it finds, parsed and ready, without you writing a single line of HTML-parsing code.
Run — free
Runs in your browser. Free, unlimited — your data never leaves this page.
The data was always there
Product pages describe their own price and availability. Recipe pages list their own ingredients and cook time. Article pages state their own author and publish date. All of it sits inside script type=application/ld+json tags because search engines asked site owners to put it there for rich results. Most of that structured data is never touched by anything except a crawler — until now, reading it programmatically meant downloading the raw HTML yourself and hand-rolling a parser that breaks the moment a site nests its markup differently.
What the call actually returns
Send a URL to POST /web/schema and get a task_id back immediately; the fetch and extraction happen asynchronously, and the finished result — every JSON-LD object found on the page, exactly as the site published it, no reinterpretation — arrives at your webhook or waits at a signed link for 24 hours. If a page defines multiple schema blocks, say a BreadcrumbList alongside a Product, both come back distinctly rather than merged into a guess.
Why JSON-LD became the standard
Structured data on the web went through a messier phase of microdata and RDFa, both of which required interleaving markup directly into visible HTML. JSON-LD won out because it lives in its own script tag, separate from layout, so a redesign doesn't accidentally break the structured data and a content team can update copy without touching the schema. That separation is exactly what makes it reliable to extract: the data isn't scattered across dozens of class attributes, it's sitting in one clean block per type.
Where this fits an automated pipeline
A monitoring system that watches a competitor's pricing, a research tool building a dataset of recipes, or an SEO audit that checks whether a client's product pages actually emit valid Product schema all need the same first step: reliable extraction at scale. Because each call is billed per request with no subscription tier games, checking ten thousand product pages nightly costs the same per page as checking one, and failed fetches — a page that returns no schema or times out — are never charged, so a scan across a messy list of URLs doesn't waste budget on the pages that don't cooperate.
What you can do with it
Competitor price monitoring
Pull Product schema nightly from a list of competitor pages to track price and availability changes without scraping visible page layout.
SEO structured-data audits
Check whether client product, article or FAQ pages actually emit valid JSON-LD before a rich-result eligibility review.
Recipe and review dataset building
Collect Recipe or Review schema across thousands of URLs to build a structured dataset without parsing raw HTML by hand.
Content aggregation feeds
Extract Article or Event schema from partner sites to populate a listings page with consistent, structured fields.
FAQ
How do I extract JSON-LD with the API?
POST the page URL to /web/schema, keep the returned task_id, and collect the extracted JSON-LD objects by webhook or a signed link valid for 24 hours.
Is the schema extraction API free?
No, there is no free tier or trial; it costs $0.002 per request, and a failed extraction is never charged.
What does it return if a page has no JSON-LD?
An empty result set — the task still completes successfully, it simply reports that no structured data was found on that page.
Does it support microdata or RDFa too?
No, this endpoint targets JSON-LD specifically, which is the format modern search engines and most sites actually use for rich results.
Can it handle pages with multiple schema types?
Yes, every JSON-LD block on the page is returned distinctly, so a page with both Product and BreadcrumbList schema returns both separately.
Can I extract schema from thousands of URLs in bulk?
Yes, submit one async task per URL and collect each result by webhook as it completes, which scales cleanly for large audits.
Does it execute JavaScript to find dynamically injected schema?
The endpoint fetches and parses the page as delivered; schema injected purely client-side after complex rendering should be tested against a specific URL before relying on it at scale.
Is the page content stored after extraction?
No, fetched pages and extracted data are deleted after the retention window and are never used for training.
For developers — API access
Everything on this page is available programmatically. This section is for teams who want to wire it into their own systems; everyone else can just use the tool above.
API endpoint
Prefer to automate it? One authenticated POST creates the task; the result comes back by webhook or a signed link. The same capability also runs here on the web, and soon from our app, email and Telegram.
Call it from your stack
curl -X POST https://api.kit.forhosting.com/web/schema \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"url":"https://ejemplo.com"}'const res = await fetch("https://api.kit.forhosting.com/web/schema", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"url": "https://ejemplo.com"
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/web/schema",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"url": "https://ejemplo.com"
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/web/schema", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"url":"https://ejemplo.com"}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"url":"https://ejemplo.com"}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/web/schema", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"url": "https://ejemplo.com"
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "web.schema",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}The API is asynchronous: the call returns a task_id immediately and the result arrives by webhook. Polling is capped at 1 req/s per task.
Pricing
Published price — no tokens, no invented credits. A failed task is never charged.
Limits
timeout_sec | 30 |
max_crawl_pages | 25 |
Errors
| HTTP | Code | Meaning |
|---|---|---|
401 | unauthorized | Missing or invalid API key. |
402 | insufficient_balance | Your balance doesn't cover the task price. |
404 | unknown_type | That task type doesn't exist. |
429 | rate_limited | Too many requests. Use the webhook instead of polling. |