Skip to main content

Parse

Turn documents — PDFs, Word, Excel, PowerPoint, and more — into clean markdown, per-page content, layout blocks, and structured JSON
6 min read

Parse converts documents into clean, LLM-ready data. Upload a file to /parse — or point /scrape at a public document URL — and get back markdown, per-page content, typed layout blocks, or structured JSON.

  • Layout-aware: headings, paragraphs, tables, and formulas assembled in reading order
  • Scans included: native text extraction with OCR fallback for image-only pages
  • Grounded structure: typed layout blocks with bounding boxes and character-span links into the markdown (PDFs)
  • Any common format: PDF, Word, Excel, PowerPoint, OpenDocument, EPUB, CSV, HTML
  • Zero Data Retention support

Quickstart#

Note

Have a public document URL instead of a file? /scrape detects the file type and parses it identically — same options, same output: firecrawl.scrape("https://example.com/report.pdf").

Response#

SDKs return the document object directly. cURL returns the JSON payload.

Note

numPages is the number of pages actually parsed; totalPages is the document's true page count. They match unless maxPages truncated the result — e.g. parsing a 100-page PDF with maxPages: 10 returns numPages: 10 and totalPages: 100, so totalPages > numPages tells you the output was truncated. totalPages is omitted when the page count can't be determined.

Beyond the document markdown, three outputs cover the cases where a single markdown string isn't enough: per-page markdown and layout blocks for PDF documents, and structured JSON for every format. And when all you need is page attribution inside the markdown itself, page markers annotate the page breaks in place.

Per-page markdown (PDF)#

Set pages: true on the PDF parser and the document also carries a pages array with the physical per-page markdown — useful when you need to know which page content came from, or to process pages independently. No additional cost.

Page markers (PDF)#

Set pageMarkers: true on the PDF parser and pages in the document markdown itself are joined with an HTML-comment marker naming the physical page that follows:

There is no new response field — the markers travel inside the markdown, so any downstream pipeline that only handles a markdown string keeps per-page attribution. The comments are invisible when the markdown is rendered and trivial to split on (<!-- page N -->, 1-based). No additional cost.

Note

Markers appear between pages only — there is no leading marker for page 1. Numbering may skip a page when the parser merges content across a page break (a table or sentence continuing onto the next page leaves no boundary to mark). Use pages: true when you need every physical page separately; the two options compose.

Layout blocks (PDF)#

Set blocks: true on the PDF parser and the document also carries a blocks array: for every page, the typed layout blocks the parsing engine detected, with geometry and provenance. This is the structured counterpart to the markdown — use it for citation grounding, highlight overlays, or auditing what a document contains. No additional cost.

A parsed PDF page with colored bounding boxes overlaid on each detected layout block: title, text, section headers, table, figure, caption, page footer, and page number
Every block the engine detects, typed and positioned — the same regions that become the markdown.

Block fields#

FieldDescription
idStable within a response: p<page>.b<index in reading order>.
typeBlock type: title, section_header, text, table, formula, figure, caption, page_number, page_header, page_footer. New types may appear over time.
labelRaw layout-model label, passthrough for forward compatibility.
bbox[x0, y0, x1, y1] normalized 0–1 relative to the page. Multiply by width/height for pixel coordinates. null when the page has no known dimensions.
contentThe markdown fragment this block contributed.
markdownSpan[start, end) character offsets into the document markdown covering this block's fragment. null when post-processing rewrote the fragment.
readingOrderPosition in the detected reading order.
sourcePipeline path that produced the block (e.g. native_text, layout_ocr, tsr, formula_model).
confidencelayout detection score (0–1) and ocr text confidence where the source provides one; null otherwise — never an invented aggregate.

Grounding: from an answer back to the page#

markdownSpan links every block to the exact substring of the markdown it produced. That makes citation grounding a lookup, not an inference: find the quoted text in the markdown, find the block whose span covers that offset, and you have the page number and bounding box — without ever asking a language model for coordinates.

Structured JSON output#

Pass a JSON schema or prompt to extract structured data directly from the document:

PDF options#

All PDF behavior is controlled through the parsers option — on /parse and /scrape alike:

PropertyTypeDefaultDescription
type"pdf"(required)Parser type.
mode"fast" | "auto" | "ocr""auto"Parsing strategy — see below.
maxPagesintegerCap the number of pages to parse.
pagesbooleanfalseAlso return per-page markdown. No additional cost.
blocksbooleanfalseAlso return layout blocks with bounding boxes. No additional cost.
pageMarkersbooleanfalseAnnotate page breaks in the document markdown with <!-- page N --> markers. No additional cost.

Passing parsers: [] skips parsing entirely and returns the PDF as base64 (1 credit flat).

Parsing modes#

ModeDescription
autoAttempts fast text-based extraction first, falls back to OCR when a page needs it. This is the default.
fastText-based extraction only (embedded text). Fastest option, but fails on scanned or image-only pages rather than silently returning nothing.
ocrForces OCR on every page. Use for scanned documents or when auto misclassifies a page.

Supported formats#

Extensions: .html, .htm, .xhtml, .pdf, .docx, .doc, .docm, .odt, .ods, .odp, .rtf, .xlsx, .xls, .xlsm, .xlsb, .pptx, .ppt, .pptm, .epub, .csv.

See Document Parsing for how each format is converted.

Request reference#

The request is multipart/form-data with a required file part and an optional options JSON part. options accepts a subset of scrape options:

  • formats: Array of output formats. Defaults to ["markdown"]. Supported: markdown, html, rawHtml, links, images, summary, and json (with a schema or prompt).
  • onlyMainContent: Only return the main content of the document. Defaults to true.
  • includeTags / excludeTags: Tag-level inclusion or exclusion (HTML inputs).
  • redactPII: Redact personally identifiable information from returned markdown.
  • timeout: Request timeout in milliseconds. Defaults to 30000, max 300000.
  • parsers: File-parser controls — see PDF options.
Note

/parse does not support browser-only options like actions, waitFor, location, mobile, or change tracking.

Tip

Using Firecrawl through MCP? Use firecrawl_parse for local files. Local MCP can read the file directly when configured with FIRECRAWL_API_URL. Remote hosted MCP returns a short-lived upload command first, then parses the returned uploadRef. Public document URLs should still use /scrape.

Considerations#

  • Maximum file size is 50 MB per request.
  • PDF parsing is billed at 1 credit per page; the pages, blocks, and pageMarkers options add no cost.
  • Parsing very large or scanned PDFs in ocr mode may take longer — increase timeout or use maxPages to bound the work.
  • For batches of files, call /parse per file in parallel; there is no batch upload variant.

Are you an AI agent that needs a Firecrawl API key? See firecrawl.dev/agent-onboarding/SKILL.md for automated onboarding instructions.