# How to Use pdf‑inspector WebAssembly: A Complete Guide to Browser‑Native PDF Processing

> Learn how to use pdf-inspector WebAssembly for client-side PDF processing directly in your browser. Analyze PDFs without server uploads with this complete guide.

- Repository: [Firecrawl/pdf-inspector](https://github.com/firecrawl/pdf-inspector)
- Tags: how-to-guide
- Published: 2026-08-31

---

**pdf‑inspector WebAssembly lets you run the full Rust PDF analysis engine directly in the browser, processing PDFs client‑side without sending bytes to any server.**

The `firecrawl/pdf-inspector` repository ships a lightweight WASM bundle built with **wasm‑bindgen**, exposing a synchronous JavaScript API for PDF classification, Markdown extraction, and text processing. This guide walks through the architecture, installation, and practical usage patterns based on the actual source code implementation.

---

## WebAssembly Module Architecture

The WASM binding layer lives in [[`wasm/src/lib.rs`](https://github.com/firecrawl/pdf-inspector/blob/main/wasm/src/lib.rs)](https://github.com/firecrawl/pdf-inspector/blob/main/wasm/src/lib.rs) and follows a clean separation between JavaScript interop and core Rust logic.

### TypeScript Type Generation

The module embeds custom TypeScript definitions via `#[wasm_bindgen(typescript_custom_section)]` ([source line 8‑66](https://github.com/firecrawl/pdf-inspector/blob/main/wasm/src/lib.rs#L8-L66)). This provides IDE autocomplete for `processPdf` options including `pages`, `password`, `profile`, and `includePageMarkers`.

### Option Handling Pipeline

Two functions bridge JavaScript inputs to Rust internals:

- **`deserialize_options`** ([source line 78‑84](https://github.com/firecrawl/pdf-inspector/blob/main/wasm/src/lib.rs#L78-L84)) — Converts `JsValue` into `WasmProcessOptions`, gracefully handling `undefined`/`null`.
- **`build_options`** ([source line 86‑118](https://github.com/firecrawl/pdf-inspector/blob/main/wasm/src/lib.rs#L86-L118)) — Maps `WasmProcessOptions` to core `PdfOptions`, validating 1‑indexed page numbers and converting `profile` strings (`"fidelity"` or `"compact"`) to the `MarkdownProfile` enum.

### Processing Entry Point

The `process_pdf` function ([source line 29‑40](https://github.com/firecrawl/pdf-inspector/blob/main/wasm/src/lib.rs#L29-L40)) orchestrates execution:

1. Calls `initialize()` to install `console_error_panic_hook` for readable JavaScript stack traces ([source line 25‑27](https://github.com/firecrawl/pdf-inspector/blob/main/wasm/src/lib.rs#L25-L27)).
2. Builds `PdfOptions` with `ProcessMode::Full`.
3. Measures timing via `js_sys::Date::now()`.
4. Delegates to `pdf_inspector::process_pdf_mem_with_options` ([source line 35‑36](https://github.com/firecrawl/pdf-inspector/blob/main/wasm/src/lib.rs#L35-L36)).
5. Wraps results in `WasmPdfProcessResult` and serializes to JavaScript.

All exported functions—`detectPdf`, `classifyPdf`, `extractText`, and `version`—follow this same pattern, varying only in `ProcessMode` and return shape.

---

## WebAssembly API Reference

| Export | Description | Process Mode |
|--------|-------------|--------------|
| `processPdf(data, options?)` | Full classification + structured Markdown extraction | `Full` |
| `detectPdf(data, options?)` | Classification only, no Markdown | `Detect` |
| `classifyPdf(data)` | Lightweight classification matching Node.js API shape | `Classify` |
| `extractText(data)` | Plain text without Markdown formatting | `Extract` |
| `version()` | Returns WASM package version string | — |

After the initial asynchronous `init()` call to load the binary, **all functions are synchronous**—enabling straightforward integration in UI components or Web Workers.

---

## Installing and Initializing pdf‑inspector WebAssembly

Add the package via npm:

```bash
npm install @firecrawl/pdf-inspector-wasm

```

The entry point exports an `init` function that must be called once before using any processing functions:

```typescript
import init, { processPdf, detectPdf, classifyPdf, extractText, version } from "@firecrawl/pdf-inspector-wasm";

async function initialize() {
  // Required: loads the .wasm binary into memory
  await init();
  console.log("WASM ready, version:", version());
}

initialize();

```

---

## Processing PDFs in the Browser: Code Examples

### Full Processing with Markdown Extraction

Load a PDF via fetch and extract structured Markdown:

```typescript
import init, { processPdf } from "@firecrawl/pdf-inspector-wasm";

async function extractMarkdown(pdfUrl: string) {
  await init();
  
  const response = await fetch(pdfUrl);
  const pdfBytes = new Uint8Array(await response.arrayBuffer());
  
  const result = processPdf(pdfBytes);
  
  console.log("PDF type:", result.pdfType);           // "TextBased" | "Scanned" | "Mixed" | "ImageBased"
  console.log("Pages needing OCR:", result.pagesNeedingOcr);
  console.log("Markdown:", result.markdown);          // Structured markdown string
  console.log("Processing time (ms):", result.durationMs);
  
  return result;
}

```

### Lightweight Detection Only

For scenarios where you only need classification without extraction:

```typescript
import init, { detectPdf } from "@firecrawl/pdf-inspector-wasm";

async function quickDetect(pdfBytes: Uint8Array) {
  await init();
  
  const result = detectPdf(pdfBytes);
  // result contains pdfType, pageCount, confidence scores
  console.log("Detected:", result.pdfType);
  
  return result;
}

```

### Selective Page Processing with Options

Process specific pages and choose output formatting:

```typescript
import init, { processPdf } from "@firecrawl/pdf-inspector-wasm";

async function selectiveExtract(pdfBytes: Uint8Array) {
  await init();
  
  const options = {
    pages: [1, 3, 5, 7, 9],           // 1-indexed page numbers
    profile: "compact",                // "fidelity" or "compact"
    includePageMarkers: true,          // Insert `<!-- Page N -->` markers
    password: undefined,               // Optional: decryption password
  };
  
  const result = processPdf(pdfBytes, options);
  console.log(result.markdown);
}

```

### Plain Text Extraction

Skip Markdown formatting entirely:

```typescript
import init, { extractText } from "@firecrawl/pdf-inspector-wasm";

async function getPlainText(pdfBytes: Uint8Array) {
  await init();
  
  const text = extractText(pdfBytes);
  // Returns raw concatenated text without structural formatting
  return text;
}

```

### Node.js‑Compatible Classification

Match the API shape used by server‑side bindings:

```typescript
import init, { classifyPdf } from "@firecrawl/pdf-inspector-wasm";

async function classify(pdfBytes: Uint8Array) {
  await init();
  
  const classification = classifyPdf(pdfBytes);
  // Minimal shape: { pdfType, confidence, isScanned, pageCount }
  return classification;
}

```

---

## Client‑Side Security Model

The parser runs **entirely within the browser**—no PDF bytes are transmitted to external servers ([source line 45‑48](https://github.com/firecrawl/pdf-inspector/blob/main/wasm/README.md#L45-L48) of the WASM README). This architecture suits:

- Privacy‑sensitive document processing
- Healthcare or financial applications with compliance requirements
- Offline‑capable web applications

---

## Key Source Files

| File | Purpose |
|------|---------|
| [[`wasm/README.md`](https://github.com/firecrawl/pdf-inspector/blob/main/wasm/README.md)](https://github.com/firecrawl/pdf-inspector/blob/main/wasm/README.md) | Installation, build instructions, and security notes |
| [[`wasm/src/lib.rs`](https://github.com/firecrawl/pdf-inspector/blob/main/wasm/src/lib.rs)](https://github.com/firecrawl/pdf-inspector/blob/main/wasm/src/lib.rs) | WASM binding layer: TypeScript definitions, option serialization, exported functions |
| [[`src/lib.rs`](https://github.com/firecrawl/pdf-inspector/blob/main/src/lib.rs)](https://github.com/firecrawl/pdf-inspector/blob/main/src/lib.rs) | Core public API (`process_pdf_mem_with_options`) shared by CLI, Node.js, and WASM |
| [[`src/detector.rs`](https://github.com/firecrawl/pdf-inspector/blob/main/src/detector.rs)](https://github.com/firecrawl/pdf-inspector/blob/main/src/detector.rs) | PDF type detection: TextBased, Scanned, Mixed, ImageBased classification |
| [[`src/markdown/convert.rs`](https://github.com/firecrawl/pdf-inspector/blob/main/src/markdown/convert.rs)](https://github.com/firecrawl/pdf-inspector/blob/main/src/markdown/convert.rs) | Text‑to‑Markdown conversion with profile selection |

The WASM layer is a thin wrapper around this core library—the same Rust code powers the `pdf2md` CLI tool and native Node.js bindings.

---

## Summary

- **Initialize once**: Call `init()` asynchronously to load the WASM binary, then use synchronous API calls.
- **Choose your mode**: `processPdf` for full extraction, `detectPdf` for classification, `extractText` for plain text.
- **Control output**: Use `options.pages` for selective processing and `options.profile` to toggle between `"fidelity"` and `"compact"` Markdown.
- **Stay private**: All processing happens client‑side with no network transmission of PDF data.
- **Single codebase**: The WASM module delegates to `pdf_inspector::process_pdf_mem_with_options` and related functions from the core Rust library.

---

## Frequently Asked Questions

### How do I load the WASM binary in a bundler like Vite or webpack?

The `@firecrawl/pdf-inspector-wasm` package includes the `.wasm` file as a base64‑encoded or separate asset depending on your build tool. Call `init()` without arguments to use the default bundler integration, or pass a custom URL: `init(binaryUrl)`. Check your bundler's WASM handling documentation for optimal chunking.

### Can I use pdf‑inspector WebAssembly in a Web Worker?

Yes. Since `init()` is the only async function and all processing calls are synchronous, you can load and initialize the module in a dedicated worker, then process PDFs off the main thread. Pass `Uint8Array` data via `postMessage` or `Transferable` objects.

### What PDF features trigger OCR requirements?

According to the detector implementation in [[`src/detector.rs`](https://github.com/firecrawl/pdf-inspector/blob/main/src/detector.rs)](https://github.com/firecrawl/pdf-inspector/blob/main/src/detector.rs), pages are flagged for OCR when they contain no extractable text streams, have image‑only content, or show low text density relative to page area. The `pagesNeedingOcr` array in `processPdf` results identifies these specifically.

### How does the `"compact"` profile differ from `"fidelity"`?

As implemented in [[`src/markdown/convert.rs`](https://github.com/firecrawl/pdf-inspector/blob/main/src/markdown/convert.rs)](https://github.com/firecrawl/pdf-inspector/blob/main/src/markdown/convert.rs), `"fidelity"` preserves header hierarchies, lists, and tables with structural Markdown, while `"compact"` collapses formatting to minimize token count for LLM consumption—merging adjacent text and simplifying list markers.