# pdf2md CLI Options Explained: `--json`, `--items-json`, `--compact`, `--pages`, and `--select-pages`

> Master pdf2md CLI options like --json, --items-json, --compact, --pages, and --select-pages. Customize PDF to Markdown extraction with structured output and page control.

- Repository: [Firecrawl/pdf-inspector](https://github.com/firecrawl/pdf-inspector)
- Tags: api-reference
- Published: 2026-08-14

---

**The `pdf2md` binary supports structured JSON output (`--json`, `--items-json`), compact Markdown formatting (`--compact`), and page-level control (`--pages`, `--select-pages`) to customize PDF-to-Markdown extraction.**

The `pdf2md` command-line tool is the Rust binary distributed with [firecrawl/pdf-inspector](https://github.com/firecrawl/pdf-inspector). It wraps the core `pdf-inspector` library and exposes extraction controls through a small set of well-defined flags. These options determine output format, verbosity, and which pages to process.

## How `pdf2md` Parses CLI Flags

All option handling lives in [`src/bin/pdf2md.rs`](https://github.com/firecrawl/pdf-inspector/blob/main/src/bin/pdf2md.rs). The binary builds a `PdfOptions` struct from command-line arguments, then passes it to `process_pdf_with_options` in [`src/lib.rs`](https://github.com/firecrawl/pdf-inspector/blob/main/src/lib.rs). This keeps the CLI thin and decouples user-facing flags from the extraction engine.

The argument parser uses a simple iterative scan of `std::env::args()`:

```rust
// From src/bin/pdf2md.rs — simplified pattern
let json_output = args.iter().any(|a| a == "--json");
let items_json = args.iter().any(|a| a == "--items-json");
let compact = args.iter().any(|a| a == "--compact");
let pages_only = args.iter().any(|a| a == "--pages");

```

Each flag sets a corresponding field on the options struct before the PDF is loaded.

## Output Format Options

### `--json`: Full Document as Structured JSON

The `--json` flag serializes the entire extraction result as a single JSON object. This includes:

- Detected document structure (headings, paragraphs, lists)
- Table metadata (rows, cells, headers)
- Font and layout annotations
- Bounding box coordinates

**Use case:** Integrating with downstream pipelines that consume structured data rather than Markdown text.

```bash
pdf2md report.pdf --json > report.json

```

Internally, this triggers `PdfResult::as_json()` in [`src/markdown/analysis.rs`](https://github.com/firecrawl/pdf-inspector/blob/main/src/markdown/analysis.rs).

### `--items-json`: Streaming JSON Lines

The `--items-json` flag emits each extracted **item** as a separate JSON line (newline-delimited JSON). Items include individual text lines, table cells, and images.

**Use case:** Streaming processors, incremental indexing, or tools like `jq` that work line-by-line.

```bash
pdf2md report.pdf --items-json > report.ndjson

```

This calls `PdfResult::as_items_json()`, which iterates over the internal `Vec<PdfItem>` and serializes each independently.

## Markdown Formatting Options

### `--compact`: Minified Markdown Output

The `--compact` flag enables a token-saving output profile. The extractor still produces valid Markdown, but with:

- Collapsed consecutive whitespace
- Omitted optional line breaks
- Tighter heading and list formatting

**Use case:** LLM context windows where token count matters, or storage-constrained environments.

```bash
pdf2md report.pdf --compact > report_compact.md

```

The flag sets `options.compact = true`, which `markdown::convert::render` respects by skipping pretty-printing passes. The help string confirms this behavior: `eprintln!("  --compact            Output compact Markdown")` at lines 226–236 of [`src/bin/pdf2md.rs`](https://github.com/firecrawl/pdf-inspector/blob/main/src/bin/pdf2md.rs).

## Page Selection Options

### `--pages`: List Extractable Pages

The `--pages` flag does not extract content. Instead, it outputs a JSON array of page numbers that contain at least one extractable text element.

**Use case:** Pre-flight checks to determine which pages merit full processing, especially for scanned documents with mixed content.

```bash
pdf2md report.pdf --pages

# Output: [1, 3, 4, 7, 12]

```

The implementation calls `PdfResult::pages_json()`, which gathers indices from the internal `PdfDocument.page_items` map.

### `--select-pages <spec>`: Targeted Extraction

The `--select-pages` flag limits extraction to a specific page subset. The `<spec>` argument accepts:

- Single pages: `5`
- Comma-separated lists: `1,3,7`
- Inclusive ranges: `10-20`
- Mixed: `1,3,5-10,15`

```bash
pdf2md report.pdf --select-pages 1,3,5-10 --json > subset.json

```

The parser consumes the token following `--select-pages` and builds a `PageSelection` struct. The extractor then skips any page not in the selection set, reducing I/O and processing time for large documents.

## Complete Command Reference

| Flag | Argument | Effect |
|------|----------|--------|
| `--json` | none | Single JSON object with full structure |
| `--items-json` | none | One JSON line per extracted item |
| `--compact` | none | Minified Markdown without extra whitespace |
| `--pages` | none | JSON array of pages with extractable content |
| `--select-pages` | `<pagespec>` | Restrict extraction to specified pages |
| `--raw` | none | Plain text without Markdown formatting |

## Example Workflows

**Structured data pipeline:**

```bash
pdf2md invoice.pdf --json | jq '.tables[0].rows' > table_data.json

```

**Incremental processing of a large document:**

```bash
pdf2md textbook.pdf --items-json | head -1000 | jq -c 'select(.type == "heading")'

```

**Token-optimized LLM ingestion:**

```bash
pdf2md research_paper.pdf --compact --select-pages 1,5-8 > llm_context.md

```

**Discover content distribution before full extraction:**

```bash
pdf2md scanned_report.pdf --pages

# Then: pdf2md scanned_report.pdf --select-pages 2,7,12-15 --json

```

## Summary

- **`--json`** produces a single structured JSON object via `PdfResult::as_json()`.
- **`--items-json`** streams per-item JSON lines via `PdfResult::as_items_json()`.
- **`--compact`** trims whitespace in Markdown output through `options.compact`.
- **`--pages`** returns a JSON array of extractable page numbers without processing content.
- **`--select-pages`** restricts extraction to user-specified pages using the `PageSelection` parser.

All flags are defined in [`src/bin/pdf2md.rs`](https://github.com/firecrawl/pdf-inspector/blob/main/src/bin/pdf2md.rs) and operate by configuring `PdfOptions` before calling `process_pdf_with_options` from [`src/lib.rs`](https://github.com/firecrawl/pdf-inspector/blob/main/src/lib.rs).

## Frequently Asked Questions

### What is the difference between `--json` and `--items-json`?

`--json` outputs one complete JSON object containing the entire document structure—headings, paragraphs, tables, and metadata as nested fields. `--items-json` outputs each extracted element as its own JSON line, useful for streaming and line-oriented tools. Choose `--json` for document-level analysis and `--items-json` for item-level filtering.

### Does `--compact` affect JSON output?

No. The `--compact` flag only affects Markdown generation in `markdown::convert::render`. JSON output from `--json` and `--items-json` is always minified (no extra whitespace) because the serializer uses default compact formatting. To pretty-print JSON, pipe through `jq .` or similar.

### Can `--select-pages` and `--pages` be used together?

Yes, but it is usually redundant. `--pages` simply lists which pages contain text; `--select-pages` then extracts from a subset. A typical workflow runs `--pages` first to inspect the document, then runs `--select-pages` with specific values for the actual extraction.

### How does `pdf2md` handle invalid page specifications?

The `PageSelection` parser in [`src/lib.rs`](https://github.com/firecrawl/pdf-inspector/blob/main/src/lib.rs) validates the specification against the actual page count of the loaded PDF. Out-of-range pages are silently ignored. Malformed specifications (non-numeric characters, unclosed ranges) typically cause the CLI to print usage information and exit with a non-zero status.