Fetch a JSON endpoint and cache the response for every repeat call
To fetch JSON from a URL through an API, you want the body parsed, the shape untouched and repeat calls answered from cache. Public datasets, third-party APIs with tight rate limits, config files and the JSON endpoints behind a single-page app all fit the pattern. The Scraping API reads them with one rule and caches the result.
Every client that calls a slow JSON API pays for it again
A dashboard that reads a public API on every page view, a build step that pulls the same dataset a hundred times, a frontend that hits a rate-limited endpoint directly: each request goes all the way to the origin, waits for it and burns its quota, even when the answer has not changed in hours.
The usual fix is a small caching service in front of the API. Now you run a server, choose a store, write expiry logic and handle the stampede when a popular key expires. Treating the endpoint as a web page to scrape is worse: a browser wraps the JSON in markup that you then have to strip.
A rule with attr: 'json' parses the response body with JSON.parse and returns it with its original shape, no URL rewriting and no value normalization. prerender: false fetches it without a browser, and every response is cached for 24 hours by default, tunable with ttl and served stale while refreshing with staleTtl.
How to scrape a JSON endpoint and cache the response
One rule reads the body, two options control freshness. The extract JSON section of the defining rules guide documents the parsing behavior.
import createClient from 'microlink.io'
const microlink = createClient({
apiKey: process.env.MICROLINK_API_KEY
})
const { content } = await microlink.extract(
'https://pokeapi.co/api/v2/pokemon',
{ content: { attr: 'json' } },
{ prerender: false }
)
console.log(content.count, content.results.length)content is the parsed body as native objects and arrays. Microlink reads the body directly, or the contents of a pre element when a browser wrapped it, so the rule works either way.
import createClient from 'microlink.io'
const microlink = createClient({
apiKey: process.env.MICROLINK_API_KEY
})
const { content } = await microlink.extract(
'https://pokeapi.co/api/v2/pokemon',
{ content: { attr: 'json' } },
{ prerender: false, ttl: '1d', staleTtl: 0 }
)ttl keeps the response for a day and staleTtl 0 serves the cached copy instantly while a fresh one is generated in the background. Both are Pro options.
curl 'https://api.microlink.io/?url=https%3A%2F%2Fpokeapi.co%2Fapi%2Fv2%2Fpokemon&data.content.attr=json&meta=false&prerender=false&filter=content.results'filter with dot notation trims the payload to content.results, so a large endpoint returns only the array your client reads.
- attr json parses the whole body. It is whole-page only and cannot be combined with selector.
- prerender false fetches the endpoint with a plain HTTP request, no browser.
- ttl How long the response stays cached, from 1 minute to 31 days. Default 24 hours. Pro plans.
- staleTtl Serves the stale copy while revalidating in the background. Cannot exceed ttl. Pro plans.
- filter Keeps only the listed fields of the response, with dot notation for nested ones.
- force Bypasses the cache for one request when you need the origin’s current answer.
The x-cache-status response header reads HIT when a response came from cache and MISS when it was fetched fresh, and x-cache-ttl shows the effective lifetime. The caching patterns guide lists every cache header and recommended TTLs by content type.
Why a cached JSON fetch beats running your own caching proxy
The cache, the expiry and the background refresh are already there. You pick the lifetime per request instead of deploying a service to hold it.
When the JSON sits inside an HTML page instead of a dedicated endpoint, go back to selectors in scrape any website to JSON.
Rate-limited or slow upstreams benefit most. For crawl-scale refresh schedules, bulk Markdown conversion with caching shows ttl and staleTtl at volume.
When not to: an endpoint you own is better cached with its own HTTP cache headers. For per-user APIs, cached copies are keyed by URL and query parameters, not by token, so read scraping behind a login and add a cacheKey per user.
FAQ
How do I fetch JSON from a URL through the API?
Can I combine attr json with a CSS selector?
How long are cached API responses kept?
Do cached JSON responses count against my quota?
Can I trim a large JSON API response to the fields I need?
Solve the next problem with the same API
Any website to JSON
Scraping behind a login
JavaScript with npm packages
Tables and lists to JSON arrays
Bulk Markdown conversion with caching
Link previews at scale
Ready to cache any JSON endpoint?
Parsed JSON with its shape intact and a cache you set per request. Start on the free tier and add ttl when you move to Pro.