Website to Markdown API
Any page, PDF or document as clean Markdown.
The Website to Markdown API reads one page, PDF or document and returns it as clean Markdown: headings, lists, links and tables kept; menus, banners and footers left out. It's the text an AI model or a search index wants.
Call it
curl https://data.upscrape.com/markdown \ -H "Authorization: Bearer $UPSCRAPE_API_KEY" \ -H "Content-Type: application/json" \ -H "Prefer: wait=30" \ -d '{"url": "https://stripe.com/privacy"}'
import osimport requestsjob = requests.post( "https://data.upscrape.com/markdown", headers={"Authorization": f"Bearer {os.environ['UPSCRAPE_API_KEY']}", "Prefer": "wait=30"}, json={"url": "https://stripe.com/privacy"},).json()print(job["results"][0]["data"]["parsed"]["markdown"])
const res = await fetch("https://data.upscrape.com/markdown", { method: "POST", headers: { Authorization: `Bearer ${process.env.UPSCRAPE_API_KEY}`, "Content-Type": "application/json", Prefer: "wait=30", }, body: JSON.stringify({ url: "https://stripe.com/privacy" }),});const job = await res.json();console.log(job.results[0].data.parsed.markdown);
The Markdown is in results[0].data.parsed.markdown. The start of it, from a run on staging on 16 October 2026:
# Privacy Policy#### Last updated: April 28, 2026This Privacy Policy includes important information about your personal data…
Files, not only pages
PDF, Word, Excel, CSV, JSON, XML and RSS or Atom feeds are read the same way: send their URL. Tables in them come back as Markdown tables and in parsed.tables.
Choose what to keep
| Input | What it does |
|---|---|
main_content_only | On by default: only the page's main content. Turn it off for the whole page. |
include_selectors | Keep only the first element matching one of these, such as "article" or ".post-body". |
exclude_selectors | Drop elements matching these, such as ".newsletter". |
detail | standard (default) is the clean content; summary is the metadata only; full adds every element, image and link found. |
headers | Extra request headers for this page, such as Accept-Language. |
Big pages
A page larger than the size limit fails with response_too_large. Raise max_body_bytes, or set allow_truncated: true to keep what was read; the response then says it was cut.
Something missing or unclear? Ask the team that builds the endpoints.