Introduction : les défis de l'analyse PDF

En tant que développeur, traiter des documents PDF est une nécessité incontournable — analyse de factures, extraction de contrats, scraping d'articles de recherche, archivage de données, presque chaque projet backend y est confronté. Mais l'analyse PDF reste depuis longtemps un casse-tête :

  • Les services OCR sont coûteux : les API cloud OCR coûtent quelques centimes par page, et les coûts explosent à grande échelle
  • Les solutions open source sont lentes : PyMuPDF4LLM met 17 secondes pour traiter 200 documents, MarkItDown en met 16
  • Perte de formatage : les outils d'extraction traditionnels ne renvoient que du texte brut — hiérarchie des titres, structure des tableaux, blocs de code, tout disparaît
  • Absence de routage intelligent : impossible de distinguer automatiquement les PDF scannés des PDF texte natifs, ce qui conduit à passer par l'OCR même pour les documents qui n'en ont pas besoin

En juillet 2026, la célèbre plateforme de scraping web Firecrawl a open sourcé une bibliothèque d'analyse PDF écrite en Rust : pdf-inspector. En seulement quelques semaines, elle a cumulé plus de 7 900 Stars, figurant parmi les trois premiers du classement quotidien GitHub Trending. Elle promet une classification et une extraction de texte PDF locales en moins de 200 ms, avec une sortie Markdown structurée — sans OCR, sans service externe.

Voyons en détail ce projet et comprenons comment il parvient à surpasser les solutions existantes en termes de performances.

Qu'est-ce que pdf-inspector ?

pdf-inspector est une bibliothèque de classification et d'extraction de texte PDF écrite en Rust par l'équipe Firecrawl. Ses capacités principales incluent :

  1. Classification intelligente — Détection du type de PDF en 10 à 50 ms : texte natif (TextBased), scan (Scanned), image (ImageBased) ou mixte (Mixed), avec niveau de confiance et recommandations de routage OCR page par page
  2. Extraction de texte — Extraction avec conscience de la position, incluant les informations de police, les coordonnées X/Y, et l'ordre de lecture multi-colonnes automatique
  3. Conversion Markdown — Détection automatique des titres H1-H4, des listes, des blocs de code (détection de police à largeur fixe), des tableaux, du gras/italique, des liens URL et des sauts de page
  4. Détection de tableaux — Double mode de détection (détection rectangulaire basée sur les opérations de dessin PDF + détection heuristique basée sur l'alignement du texte), pour traiter parfaitement les rapports financiers et les tableaux multi-pages
  5. Support des polices CID — Décodage ToUnicode CMap, support des polices Type0/Identity-H, encodages UTF-16BE, UTF-8 et Latin-1
  6. Bindings multi-langages — Disponibles en Python, Node.js et WebAssembly pour navigateur

Pourquoi Rust ? Les abstractions à coût zéro et la sécurité mémoire de Rust permettent à pdf-inspector d'atteindre des vitesses d'analyse extrêmes sans dépendre de modèles ML ni de services externes. La bibliothèque n'a qu'une seule dépendance externe : lopdf (bibliothèque d'analyse PDF en Rust).

Comparaison de performances

Selon les benchmarks officiels sur Apple M4 Pro (200 documents, corpus opendataloader-bench) :

Moteur Score global Ordre de lecture Reconnaissance de tableaux Reconnaissance de titres Temps pour 200 documents
pdf-inspector 0,875 0,915 0,814 0,788 0,470 s
LiteParse 0,873 0,913 0,693 0,811 0,750 s
OpenDataLoader 0,831 0,902 0,489 0,739 2,569 s
PyMuPDF4LLM 0,735 0,886 0,401 0,424 17,169 s
MarkItDown 0,589 0,844 0,273 0,000 16,117 s

pdf-inspector domine en score global, ordre de lecture, reconnaissance de tableaux et vitesse — il est 36 fois plus rapide que PyMuPDF4LLM et 34 fois plus rapide que MarkItDown.

Installation

pdf-inspector prend en charge plusieurs méthodes d'installation, couvrant Rust, Python, Node.js et les environnements navigateur.

Rust (natif)

Ajoutez la dépendance dans votre Cargo.toml :

TOML
[dependencies]
pdf-inspector = "0.2"

Ou installez via la ligne de commande cargo :

BASH
cargo add pdf-inspector

Python

pdf-inspector fournit des bindings Python via maturin :

BASH
pip install maturin
git clone https://github.com/firecrawl/pdf-inspector.git
cd pdf-inspector
maturin develop --release

💡 Remarque : pdf-inspector n'est pas encore publié sur PyPI. L'installation doit se faire par compilation depuis les sources. L'équipe Firecrawl prévoit de publier un paquet PyPI une fois la version stable atteinte.

Node.js

BASH
npm install @firecrawl/pdf-inspector

WebAssembly pour navigateur

BASH
npm install @firecrawl/pdf-inspector-wasm

La version Wasm intègre l'analyseur Rust complet dans le navigateur et peut s'exécuter dans un Web Worker, sans aller-retour serveur.

Prise en main rapide

Exemple Python

Après l'installation, l'utilisation est très simple — un seul appel de fonction suffit :

PYTHON
import pdf_inspector

# Traiter un fichier PDF
result = pdf_inspector.process_pdf("document.pdf")

# Afficher la classification du type de PDF
print(f"Type de PDF : {result.pdf_type}")
# Sortie : "text_based", "scanned", "image_based", ou "mixed"

# Obtenir la sortie Markdown
if result.markdown:
    print(result.markdown)

C'est aussi simple que ça. Une seule ligne de code pour la classification + l'extraction + la conversion Markdown.

Exemple Node.js

JAVASCRIPT
const { processPdf } = require('@firecrawl/pdf-inspector');
const fs = require('fs');

async function analyzePdf(filePath) {
  const pdfBuffer = fs.readFileSync(filePath);
  const result = await processPdf(pdfBuffer);

  console.log('Type de PDF :', result.pdfType);
  console.log('Confiance :', result.confidence);
  console.log('--- Sortie Markdown ---');
  console.log(result.markdown);
}

analyzePdf('report.pdf');

Exemple Rust natif

RUST
use pdf_inspector::{PdfInspector, ProcessPdfResult};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let inspector = PdfInspector::new();
    let result: ProcessPdfResult = inspector.process_pdf_path("document.pdf")?;

    println!("Type de PDF : {:?}", result.pdf_type);
    println!("Confiance : {:.2}", result.confidence);

    if let Some(markdown) = result.markdown {
        println!("Markdown :\n{}", markdown);
    }

    Ok(())
}

Fonctionnalités principales en détail

1. Classification intelligente : éviter les coûts OCR inutiles

L'une des fonctionnalités les plus pratiques de pdf-inspector est la classification automatique. En échantillonnant les flux de contenu du PDF, il détermine le type de document en 10 à 50 ms :

Type Description Stratégie recommandée
text_based PDF texte natif, avec des flux de texte extractibles Extraire directement avec pdf-inspector, ignorer l'OCR
scanned Document numérisé (pages images) Nécessite un service OCR
image_based PDF principalement composé d'images (ex. : collections de captures d'écran) Nécessite OCR ou traitement d'image
mixed Type mixte (certaines pages ont du texte, d'autres sont scannées) Décider page par page : extraire directement les pages texte, appeler l'OCR pour les pages scannées

Scénario pratique : construire un pipeline de traitement PDF intelligent

PYTHON
import pdf_inspector
# Supposons que vous ayez votre propre fonction OCR
def smart_pdf_pipeline(pdf_path, ocr_function):
    result = pdf_inspector.process_pdf(pdf_path)

    if result.pdf_type == "text_based":
        # Texte natif, extraction directe — rapide, gratuit, précis
        print("✅ PDF texte natif, extraction directe")
        return result.markdown

    elif result.pdf_type == "scanned":
        # Document scanné, appel à l'OCR
        print("🔍 PDF scanné, appel OCR")
        return ocr_function(pdf_path)

    elif result.pdf_type == "mixed":
        # Type mixte — traitement page par page
        print("📄 PDF mixte, routage page par page")
        pages = []
        for page_info in result.page_results:
            if page_info.needs_ocr:
                pages.append(ocr_function_for_page(pdf_path, page_info.page_number))
            else:
                pages.append(page_info.markdown)
        return "\n\n".join(pages)

    else:
        # Purement image, extraction de texte impossible
        print("❌ PDF image, extraction de texte impossible")
        return None

Ce pipeline permet de sauter entièrement l'OCR pour environ 54 % des PDF (type texte natif), réduisant considérablement les coûts et la latence de traitement.

2. Conversion Markdown : préserver la structure du document

La sortie Markdown de pdf-inspector n'est pas du simple texte brut — elle identifie intelligemment et conserve la structure du document :

  • Hiérarchie des titres (H1-H4) : déduite automatiquement par les ratios de taille de police
  • Listes : détection automatique des listes à puces, numérotées et alphabétiques
  • Blocs de code : marqués automatiquement grâce à la détection des polices à largeur fixe
  • Tableaux : support de la détection rectangulaire et heuristique, pour les rapports financiers et les tableaux multi-pages
  • Gras/italique : conservation du formatage
  • Liens URL : identification et conversion automatiques en liens Markdown
  • Sauts de page : séparés par --- entre les pages

Voyons le résultat concret avec un article académique PDF :

MARKDOWN
# Deep Learning Approaches for Natural Language Processing

## 1. Introduction

Natural language processing (NLP) has seen remarkable progress in recent years...

### 1.1 Background

The transformer architecture, introduced by Vaswani et al., has become...

## 2. Methodology

| Model | BLEU Score | Training Time |
|-------|-----------|---------------|
| Transformer | 38.2 | 12 hours |
| BERT | 41.0 | 24 hours |
| GPT-4 | 45.7 | 72 hours |

## 3. Results

The experimental results demonstrate...

> **Note :** All experiments were conducted on...

Hiérarchie des titres, tableaux, blocs de citation — tout est conservé intégralement, ce qui est bien supérieur aux outils d'extraction PDF traditionnels qui ne produisent que du texte brut.

3. Détection multi-colonnes et ordre de lecture

De nombreux PDF (articles, journaux, magazines) utilisent une mise en page multi-colonnes. pdf-inspector détecte automatiquement la structure en colonnes et extrait dans le bon ordre de lecture :

PYTHON
result = pdf_inspector.process_pdf("newspaper.pdf")

# pdf-inspector détecte automatiquement les mises en page deux/trois colonnes
# et produit la sortie dans le bon ordre : de haut en bas, de gauche à droite
print(result.markdown)

Il prend également en charge les textes RTL (de droite à gauche), adaptés aux documents en arabe, hébreu, etc.

4. Polices CID et détection des problèmes d'encodage

Lors du traitement de PDF en chinois, japonais ou coréen, les encodages de polices posent souvent problème. pdf-inspector prend en charge le décodage ToUnicode CMap et gère correctement :

  • Les polices Type0 / Identity-H
  • Les encodages UTF-16BE, UTF-8 et Latin-1
  • Le marquage automatique des encodages de polices corrompus

Cela signifie que lors du traitement de PDF en langues CJK, il peut vous indiquer quelles pages risquent d'avoir des caractères illisibles, vous permettant de décider à l'avance si un repli vers l'OCR est nécessaire.

Cas pratiques avancés : construire un service de traitement PDF

Construisons un microservice complet de traitement PDF intégrant la classification intelligente de pdf-inspector.

Scénario : système d'archivage de documents

Imaginons que vous mettiez en place un système interne d'archivage de documents en entreprise, traitant chaque jour des centaines de PDF (contrats, factures, rapports, etc.) :

PYTHON
# pdf_service.py
import os
import json
from datetime import datetime
import pdf_inspector

class PdfProcessingService:
    def __init__(self, output_dir="./processed"):
        self.output_dir = output_dir
        os.makedirs(output_dir, exist_ok=True)

    def process_batch(self, pdf_files):
        """Traiter un lot de fichiers PDF"""
        results = []
        for pdf_path in pdf_files:
            result = self.process_single(pdf_path)
            results.append(result)
        return results

    def process_single(self, pdf_path):
        """Traiter un fichier PDF individuel"""
        filename = os.path.basename(pdf_path)
        pdf_result = pdf_inspector.process_pdf(pdf_path)

        # Extraire les métadonnées
        metadata = {
            "filename": filename,
            "pdf_type": pdf_result.pdf_type,
            "confidence": pdf_result.confidence,
            "processed_at": datetime.now().isoformat(),
            "pages_count": len(pdf_result.page_results) if hasattr(pdf_result, 'page_results') else 0,
            "needs_ocr": pdf_result.pdf_type in ("scanned", "image_based"),
        }

        # Sauvegarder la sortie Markdown
        if pdf_result.markdown:
            md_filename = filename.replace(".pdf", ".md")
            md_path = os.path.join(self.output_dir, md_filename)
            with open(md_path, "w", encoding="utf-8") as f:
                f.write(pdf_result.markdown)
            metadata["markdown_path"] = md_path

        # Sauvegarder les métadonnées
        meta_path = os.path.join(
            self.output_dir,
            filename.replace(".pdf", ".meta.json")
        )
        with open(meta_path, "w", encoding="utf-8") as f:
            json.dump(metadata, f, ensure_ascii=False, indent=2)

        return metadata

# Exemple d'utilisation
service = PdfProcessingService(output_dir="./output")

# Traitement par lot
pdf_files = [
    "contracts/contract_2026_001.pdf",
    "invoices/invoice_aug_2026.pdf",
    "reports/q2_financial_report.pdf",
]

results = service.process_batch(pdf_files)
for r in results:
    status = "OCR requis" if r["needs_ocr"] else "Extraction directe"
    print(f"{r['filename']} : {r['pdf_type']} ({status})")

Scénario : intégration avec un pipeline d'analyse de documents par LLM

Le Markdown de haute qualité produit par pdf-inspector peut être directement envoyé à un LLM pour analyse :

PYTHON
import pdf_inspector
# Supposons que vous utilisiez une API compatible OpenAI
from openai import OpenAI

def analyze_pdf_with_llm(pdf_path, prompt="Résumez le contenu principal de ce document"):
    """Analyser le contenu d'un PDF avec un LLM"""
    # 1. Extraire le Markdown avec pdf-inspector
    result = pdf_inspector.process_pdf(pdf_path)

    if not result.markdown:
        return "Impossible d'extraire le contenu texte, OCR probablement nécessaire"

    # 2. Si le document est trop long, tronquer aux 8 000 premiers caractères
    markdown_content = result.markdown[:8000]

    # 3. Appeler le LLM pour l'analyse
    client = OpenAI(api_key="VOTRE_CLE_API")
    response = client.chat.completions.create(
        model="gpt-4o",
        messages=[
            {"role": "system", "content": "Vous êtes un assistant d'analyse de documents."},
            {"role": "user", "content": f"Veuillez {prompt} en vous basant sur le contenu suivant :\n\n{markdown_content}"}
        ]
    )

    return response.choices[0].message.content

# Utilisation
summary = analyze_pdf_with_llm("annual_report.pdf", "extrayez les indicateurs financiers clés")
print(summary)

Ce type de pipeline est particulièrement utile dans les systèmes RAG (Retrieval-Augmented Generation) — on extrait d'abord le texte structuré rapidement avec pdf-inspector, puis on le vectorise pour le stocker dans une base de connaissances.

Comparaison avec d'autres solutions

pdf-inspector vs PyMuPDF4LLM

Critère pdf-inspector PyMuPDF4LLM
Langage Rust Python (bindings C)
Score global 0,875 0,735
Reconnaissance de tableaux 0,814 0,401
Vitesse (200 documents) 0,47 s 17,169 s
Structure Markdown ✅ Conservée intégralement ⚠️ Partiellement perdue
Classification intelligente ✅ Intégrée ❌ Absente
Wasm navigateur ✅ Supporté ❌ Non supporté

pdf-inspector vs MarkItDown (Microsoft)

Critère pdf-inspector MarkItDown
Score global 0,875 0,589
Reconnaissance de titres 0,788 0,000
Vitesse (200 documents) 0,47 s 16,117 s
Bindings multi-langages Python/Node/Wasm Python
Spécialisation Analyse PDF dédiée Conversion de documents générique

Quand utiliser pdf-inspector, et quand utiliser l'OCR ?

  • Utilisez pdf-inspector : pour les PDF texte natifs, rapports, articles de recherche, contrats, factures — tout document avec des flux de texte extractibles
  • Utilisez l'OCR : pour les documents scannés, PDF purement images, documents manuscrits
  • Utilisation mixte : classez d'abord avec pdf-inspector, extrayez directement les text_based, passez par l'OCR pour les scanned/image_based — c'est exactement la stratégie de routage conçue par pdf-inspector

Informations sur le projet et communauté

  • GitHub : firecrawl/pdf-inspector
  • Stars : 7 900+ (lancé en juillet 2026, croissance soutenue)
  • Licence : Apache-2.0 (compatible usage commercial)
  • Langage : Rust
  • Écosystème : Produit Firecrawl (plateforme de scraping web renommée, également à l'origine du moteur de爬虫 open source firecrawl)

Canaux d'installation

Plateforme Méthode d'installation
Rust crates.io/crates/pdf-inspector
Python Compilation depuis les sources (maturin develop --release)
Node.js npm install @firecrawl/pdf-inspector
Navigateur npm install @firecrawl/pdf-inspector-wasm

Conclusion

pdf-inspector comble un vide important — une solution d'analyse PDF légère, rapide et locale. Elle ne nécessite aucun modèle ML, aucun service externe, est implémentée en Rust pur, et atteint des vitesses largement supérieures aux outils comparables tout en maintenant une haute précision.

Résumé des avantages clés :

  1. 🚀 Vitesse extrême — Analyse en ~200 ms, 36 fois plus rapide que PyMuPDF4LLM
  2. 🧠 Classification intelligente — Distinction automatique des PDF texte/scan/image, optimisation du routage OCR
  3. 📐 Préservation de la structure — Titres, tableaux, blocs de code, listes conservés intégralement en Markdown
  4. 🔒 100 % local — Aucune dépendance externe, aucun appel API, les données ne quittent jamais la machine
  5. 🌐 Multi-plateforme — Couverture complète Rust/Python/Node.js/Wasm navigateur

Si vous construisez un pipeline de traitement de documents, un système RAG ou toute application nécessitant l'analyse de PDF, pdf-inspector mérite sa place dans votre stack technique. En particulier pour les scénarios dominés par les PDF texte natifs, il vous évitera des coûts et une latence OCR considérables.

🔗 Liens utiles - GitHub : firecrawl/pdf-inspector - Documentation Python : docs/python.md - Benchmarks : opendataloader-bench - Firecrawl : firecrawl.dev