Turn any website into JSON with CSS selector rules
A website to JSON API should return the fields you asked for, typed, and nothing else. Catalog imports, lead lists, content migrations and internal dashboards all start with the same job: read a few values off a page and store them as data. With the Scraping API you describe each field as a rule and the response is the JSON object you described.
HTML is a document, not the JSON your code expects
Every page mixes the three values you need with navigation, scripts, ads and markup. Getting from that to a clean object means fetching the page, parsing it, walking the tree, trimming whitespace and converting strings into numbers, URLs and dates, once per site.
The usual stack is an HTTP client plus an HTML parser, and it quietly fails on pages that build their content in the browser, where the fetched HTML is an empty shell. Adding a headless browser fixes that and hands you a fleet to run. Either way the output is loose strings, so a missing element surfaces later as undefined deep inside your code.
The data parameter turns that into a schema. Each key is a rule: a CSS selector for the element, an attr for what to read and a type to validate it. Microlink fetches the page, renders it in a browser only when it needs to, applies the rules and returns one key per rule. The extract method is the same grammar from the SDK.
How to convert a website to JSON with CSS selector rules
Start with one field, check it, then add the rest. The defining rules guide walks through single values, collections, nested objects and fallbacks in that order.
import createClient from 'microlink.io'
const microlink = createClient({
apiKey: process.env.MICROLINK_API_KEY
})
const { title, author, published } = await microlink.extract(
'https://example.com/blog/post',
{
title: { selector: 'h1', attr: 'text' },
author: { selector: '[rel=author]', attr: 'text', type: 'author' },
published: { selector: 'time', attr: 'datetime', type: 'date' }
}
)extract resolves to an object with exactly one key per rule and none of the normalized metadata. A rule that matches nothing, or whose value fails its type, comes back as null.
import createClient from 'microlink.io'
const microlink = createClient({
apiKey: process.env.MICROLINK_API_KEY
})
const { stories } = await microlink.extract('https://news.ycombinator.com', {
stories: {
selectorAll: '.athing',
attr: {
title: { selector: '.titleline > a', attr: 'text' },
url: { selector: '.titleline > a', attr: 'href', type: 'url' }
}
}
})An object under attr is evaluated relative to each element matched by selectorAll, so the result is an array of objects. Nested rules can nest again to describe a whole section of the page.
curl 'https://api.microlink.io/?url=https%3A%2F%2Fexample.com&data.title.selector=h1&data.title.attr=text&meta=false'Rules flatten to data.title.selector and data.title.attr query parameters, so any HTTP client can call it. meta: false skips the metadata pass, usually the biggest speedup for data-only requests.
- data The output schema: one key per field, one rule per key.
- selector The first element matching a CSS selector. An array of selectors acts as a fallback list.
- attr Any HTML attribute, or text, html, outerHTML, markdown, json or val. Default html.
- type Validates and normalizes the value: number, url, date, email, image and more. Default auto.
- meta Set to false to return only your fields and skip the normalized metadata.
- filter Keeps only the listed fields in the payload, with dot notation for nested ones.
Rules run on the rendered page when one is needed: prerender defaults to auto, so client-rendered pages get a browser and static ones do not. For apps that need a wait before the data exists, see scraping JavaScript-rendered pages.
Why a declarative JSON schema beats a hand-written parser
The rule set is the scraper. It lives in one object you can version, review and reuse across pages that share a template.
A value that fails its type becomes null, which is what lets fallback rules move on to the next candidate.
Lists and rows use the same grammar: scrape tables and repeated lists shows nested rules turning each row into an object.
When not to: if you want the whole article as text for a model or a search index, a schema is overkill. Convert the page to clean Markdown instead.
FAQ
How do I convert a website to JSON with an API?
What happens when a CSS selector rule matches nothing?
Can I use the HTML to JSON API without the JavaScript SDK?
How do I get only my own fields in the JSON response?
Does scraping a website to JSON work on the free tier?
Solve the next problem with the same API
Tables and lists to JSON arrays
Product prices and stock
Custom fields from JavaScript apps
Cached JSON endpoints
Custom fields alongside metadata
Clean Markdown, no boilerplate
Ready to turn any page into JSON?
Declare the fields, get typed JSON back. Start on the free tier and write your first rule in a minute.