Convertir un PDF en Markdown avec Node.js
Trois appels et c'est terminé : créez une tâche, interrogez-la jusqu'à ce qu'elle soit prête, puis téléchargez du Markdown propre. L'exemple ci-dessous est du Node 18+ avec le fetch global, sans dépendances, sans GPU, juste l'API REST.
Créer, interroger, télécharger
L'API PDF vers Markdown est une petite API de tâches. Vous faites un POST d'un PDF (une URL ou un fichier téléversé) vers /api/v2/jobs avec votre clé API, recevez un job_id, interrogez /api/v2/jobs/{job_id} jusqu'à ce que l'état soit ready, puis téléchargez le Markdown depuis /api/v2/jobs/{job_id}/download. L'OCR, les tableaux et les formules sont traités côté serveur, il n'y a donc rien à installer dans votre app Node.
L'exemple complet
Enregistrez-le sous convert.mjs et exécutez node convert.mjs. Remplacez la clé et l'URL du PDF.
// Node 18+ has a global fetch, so no dependencies are needed.
const API = "https://pdf2md.dev/api/v2";
const H = { Authorization: "Bearer p2m_your_key" };
// 1) create a job from a PDF URL
const created = await fetch(`${API}/jobs`, {
method: "POST",
headers: { ...H, "Content-Type": "application/json", "Idempotency-Key": "report-2026-01" },
body: JSON.stringify({ url: "https://example.com/report.pdf" }),
});
if (!created.ok) throw new Error(`create failed: ${created.status}`);
const { job_id } = await created.json();
// 2) poll until ready or error
let job;
do {
await new Promise((r) => setTimeout(r, 3000));
job = await (await fetch(`${API}/jobs/${job_id}`, { headers: H })).json();
} while (!["ready", "error"].includes(job.status));
if (job.status === "error") {
throw new Error(`conversion failed: ${job.error_code} ${job.error_message}`);
}
// 3) download the Markdown
const md = await (await fetch(`${API}/jobs/${job_id}/download`, { headers: H })).text();
if (job.truncated) console.warn("note: partial result (hit the time budget)");
const fs = await import("node:fs/promises");
await fs.writeFile("report.md", md);
console.log("saved report.md");
L'Idempotency-Key rend sûr un create relancé : si la même clé est envoyée deux fois, vous récupérez la même tâche au lieu d'une conversion en double.
Ce que fait chaque appel
Créez une tâche
POST /api/v2/jobs avec la clé API comme jeton Bearer et un corps JSON de { "url": "..." }. Pour convertir un fichier local à la place, envoyez multipart/form-data avec un champ file. La réponse donne un job_id.
Interrogez jusqu'à ready
GET /api/v2/jobs/{job_id} renvoie un status de queued, processing, ready ou error. Interrogez toutes les quelques secondes jusqu'à ce qu'il se stabilise.
Téléchargez le Markdown
GET /api/v2/jobs/{job_id}/download renvoie le texte Markdown. Écrivez-le dans un fichier .md, passez-le à un LLM, ou stockez-le pour un pipeline RAG.
Erreurs, relances et fichiers volumineux
Gérez les échecs
processing_timeout, conversion_failed) ; error_message peut être journalisé en toute sécurité.ready signifie un résultat partiel ayant atteint le budget de temps sur un document très long.Passez à l'échelle
Pour convertir de nombreux PDF, exécutez les mêmes trois appels par fichier avec une petite limite de concurrence, ou passez de l'interrogation aux webhooks afin d'être notifié lorsque chaque tâche est prête. Le contrat est identique en TypeScript ; typez la réponse job et le tour est joué.
Vous préférez Python ou le shell ? Consultez le tutoriel Python et la recette cURL.
Vous construisez un agent ou un pipeline ?
La même conversion est disponible comme endpoint MCP hébergé, ainsi un agent IA peut convertir des PDF sans aucune configuration. Consultez le hub développeurs pour la référence complète de l'API et la spécification OpenAPI.
Questions fréquentes
Ai-je besoin d'une clé API pour convertir des PDF avec Node.js ?
Oui, pour l'API REST vous passez une clé API comme jeton Bearer. Vous pouvez aussi convertir de manière anonyme dans le navigateur ou l'application web sans clé ; la clé API est destinée à l'usage programmatique et automatisé.
Quelle version de Node.js me faut-il ?
Node 18 ou plus récent, qui embarque un fetch global, ainsi l'exemple ne nécessite aucune dépendance supplémentaire. Sur les versions antérieures, installez un polyfill de fetch ou utilisez une bibliothèque de requêtes.
Comment convertir un fichier PDF local au lieu d'une URL ?
Envoyez un POST multipart/form-data vers /api/v2/jobs avec le champ file pointant vers le PDF, en utilisant FormData et un Blob, au lieu d'un corps JSON avec une url. Le reste du flux (interroger, télécharger) est identique.
Comment gérer les erreurs et les délais d'attente ?
Lorsque status vaut error, lisez error_code (par exemple processing_timeout ou conversion_failed) et error_message. Un document long peut se terminer ready avec truncated à true, ce qui signifie un résultat partiel ayant atteint le budget de temps.
Puis-je utiliser des webhooks au lieu de l'interrogation ?
Oui. L'interrogation est la plus simple pour démarrer, mais l'API prend aussi en charge les webhooks afin que vous soyez notifié lorsqu'une tâche est prête au lieu d'interroger. Consultez le hub développeurs pour la configuration du webhook.