An HTML-to-JSON API driven by CSS selectors and the machine-readable data a page already publishes. Nothing is inferred, so a selector that matches nothing returns null instead of something plausible — which is the property you actually need from an extraction step.
1 / 29blocked by bot protection7 ruined by consent walls
~2smedian renderp50, viewport capture
Why a browser, and why it has to remove rather than hide
Modern extraction runs a real browser, because a plain fetch returns a shell that JavaScript was supposed to fill in. But once the browser has run, the consent dialog is in the document — and hiding it with display:none keeps it out of a screenshot, not out of the DOM. So it comes back in the text. Measured on zoom.com in August 2026: a leading browser-based markdown API returned 51 fragments of cookie-consent copy, including the full Cookie Preference Center. The same page through /v1/markdown returned none, because the nodes are detached before a word is read.
Reading https://www.zoom.com
Fragments of consent copy
What you actually get
A plain fetch + a readability parser
0
…and no article either: the page is a shell until JavaScript runs
A leading browser-based markdown API
51
including the full “Cookie Preference Center” and the OneTrust logo
rendershed /v1/markdown
0
1 overlay node detached before extraction
Measured August 2026, and it will drift as
everyone's pipelines change — the method is a regex for consent wording
over each tool's own output, which is as reproducible as it is crude. Run
it yourself before believing it.
Cosmetic is not enough for text
Suppression on the capture path is a stylesheet: the consent dialog
stops being painted, which is the whole job for a screenshot. It is
still a node, so page.content(), textContent
and every HTML parser downstream still see it. These endpoints detach
the tagged nodes first, and tell you how many in
suppressed.stripped.
Where this does not help
Worth saying plainly. Some consent managers render in a cross-origin
iframe — Sourcepoint, which fronts the Guardian and the BBC — and no
extractor can read inside one, so their copy was never going to reach
your text. And when main_only is on, the article-finding
step already drops most page furniture. The gap this closes is inline
consent managers, whole-document reads, and pages with no clear
article body.
It never clicks Accept
Declining on your behalf for a throwaway read is defensible. Agreeing
on your behalf is not. Reject buttons that are really subscription
funnels are recognised by their own label and skipped in favour of
hiding — the Guardian's is exactly that, which is why it comes back
marked ~sourcepoint.
It sees what JavaScript built
A fetch returns what the server sent, which on most of the web is a
shell. This runs the page, waits for the network to settle, and reads
the document that resulted — the same navigation a screenshot gets,
because it is the same fleet.
One render, one allowance
The same key, the same quota and the same subscription as a screenshot
or a PDF. There is no separate plan for text, and a cached call is
free because it cost us a disk read.
One call, no signup POST /v1/json→application/json
Anonymous calls run at 40 an hour against your address. A free
key raises that and works from anywhere.
# With no schema you get what the page already publishes for machines:# JSON-LD, microdata and OpenGraph. On a product or recipe page that is# usually the entire answer, and it costs you no selectors to maintain.curl-XPOST https://shots.rendershed.com/v1/json \
-H"Content-Type: application/json" \
-d'{"url": "example.com/product"}'
Map of field name to CSS selector. A value is either a bare selector, or {selector, attr, type} — attr defaults to text and may be any attribute or "html"; type may be text, number, int or boolean. Repeat a block with {selector, many: true, limit, fields: {…}}. Up to 60 fields, 3 levels deep.
auto
bool
when no schema
Harvest the structured data the page already publishes: JSON-LD, microdata and OpenGraph.
scroll
bool
false
Walk to the bottom first so lazy-loaded rows are present. Paid plans only.
device
enum
—
iphone, android or ipad.
overlay_mode
enum
dismiss
off, hide or dismiss.
Errors, response headers and the signed-URL scheme are the
same for every product — they live in the reference.
On the same key
Five outputs, one account, one quota. Every call costs one
render whichever path you use.
Screenshot APIPOST /v1/render — Screenshots of the page. Not the cookie banner.
HTML to PDF APIPOST /v1/pdf — PDFs of the page. Not the cookie banner.
URL to Markdown APIPOST /v1/markdown — The article. Not the article plus a cookie policy.
Link Preview APIPOST /v1/metadata — Previews that are right on sites that render themselves.