Converter PDF em Markdown no Python
Um tutorial passo a passo usando a API REST: obtenha uma chave, crie um job, consulte e baixe Markdown limpo, com um exemplo completo e copiável e tratamento de erros como deve ser.
Uma chave, três chamadas
Para converter um PDF em Markdown no Python você chama uma pequena API REST com uma chave bearer: POST /api/v2/jobs para criar um job, GET /api/v2/jobs/{id} para consultar até ficar pronto e depois GET /api/v2/jobs/{id}/download para o Markdown. Não há nada para hospedar nem uma biblioteca pesada para instalar, apenas requests. O mesmo ciclo de vida é exposto como um MCP hospedado para agentes, e a saída é o mesmo Markdown que a extensão e o app web produzem, então você pode prototipar no navegador e depois automatizar com confiança.
Configure em quatro passos
Obtenha uma chave de API
Entre com uma conta Google gratuita e crie uma chave de API na sua conta; ela é exibida uma única vez. Envie-a como Authorization: Bearer p2m_your_key.
Crie um job
Faça POST da URL do PDF (ou dos bytes enviados) em /api/v2/jobs. Você recebe um id de job e um status.
Consulte até ready
Faça GET /api/v2/jobs/{id} até status ser ready ou error.
Baixe o Markdown
Faça GET /api/v2/jobs/{id}/download para o texto Markdown. Respeite truncated e pages.
O script de Python completo
Biblioteca padrão mais requests. Crie a partir de uma URL de PDF, consulte e depois salve o Markdown.
# pip install requests import requests, time API = "https://pdf2md.dev/api/v2" H = {"Authorization": "Bearer p2m_your_key"} # 1) create a job from a PDF URL r = requests.post(f"{API}/jobs", headers={**H, "Idempotency-Key": "report-2026-01"}, json={"url": "https://example.com/report.pdf"}) r.raise_for_status() jid = r.json()["job_id"] # 2) poll until ready or error while True: job = requests.get(f"{API}/jobs/{jid}", headers=H).json() if job["status"] in ("ready", "error"): break time.sleep(3) if job["status"] == "error": raise SystemExit(f"conversion failed: {job.get('error_code')} {job.get('error_message')}") # 3) download the Markdown md = requests.get(f"{API}/jobs/{jid}/download", headers=H).text if job.get("truncated"): print("note: partial result (hit the time budget)") open("report.md", "w").write(md)
Enviar um arquivo local em vez de uma URL? Faça POST dos bytes como multipart/form-data com um campo file no mesmo endpoint. As formas completas da requisição e da resposta estão na especificação OpenAPI.
Para converter muitos PDFs, crie um job por arquivo e consulte-os em paralelo até o seu limite de espaços (3 no plano gratuito, mais nos pagos). Mantenha um Idempotency-Key distinto por arquivo para que as novas tentativas nunca dupliquem trabalho, e recue diante de um 429 usando o cabeçalho Retry-After.
Erros, novas tentativas e webhooks
Leia o código de erro
Um job que falha retorna status: error com um error_code legível por máquina (processing_timeout ou conversion_failed) e um error_message seguro: ramifique pelo código, não pelo texto.
Trate truncated
Um documento longo pode voltar ready com truncated=true. Verifique a marca e divida o arquivo ou use um orçamento pago maior.
Idempotency-Key
Envie um cabeçalho Idempotency-Key para que um create repetido retorne o mesmo job em vez de duplicar trabalho.
Webhooks em vez de consulta
Nos planos pagos, registre um webhook ou passe callback_url e receba um POST em ready/error em vez de consultar.
Respeite o 429
Diante de um 429, espere os segundos de Retry-After antes de tentar de novo; não sature a fila.
Mantenha as chaves no servidor
A chave é um segredo: guarde-a no servidor, envie por TLS, e rotacione-a ou revogue-a quando quiser.
Não usa Python? As mesmas três chamadas
É uma API HTTPS simples, então qualquer linguagem funciona. O mesmo criar / consultar / baixar em Node:
// Node 18+ (global fetch) const API = "https://pdf2md.dev/api/v2"; const H = { Authorization: "Bearer p2m_your_key" }; let r = await fetch(`${API}/jobs`, { method: "POST", headers: { ...H, "Content-Type": "application/json" }, body: JSON.stringify({ url: "https://example.com/report.pdf" }) }); let { job_id } = await r.json(); let job; do { await new Promise(s => setTimeout(s, 3000)); job = await (await fetch(`${API}/jobs/${job_id}`, { headers: H })).json(); } while (!["ready", "error"].includes(job.status)); const md = await (await fetch(`${API}/jobs/${job_id}/download`, { headers: H })).text();
Prefere ferramentas de agente ou RAG?
O mesmo ciclo de vida é um MCP hospedado para ChatGPT, Claude e frameworks de agentes. Para ingestão e chunking, consulte o guia de RAG.
Perguntas comuns
Como converto um PDF em Markdown no Python?
Chame a API REST com uma chave bearer: faça POST do PDF em /api/v2/jobs, consulte GET /api/v2/jobs/{id} até ready e depois faça GET de /download para o Markdown. O exemplo completo com requests está acima.
Preciso de uma chave de API?
Sim, para a API. Uma conta Google gratuita permite criar uma chave e usar o MCP hospedado. A extensão do navegador e o app web continuam anônimos e não precisam de chave.
Como trato erros e tempos de espera?
Um job que falha retorna status: error com um error_code legível por máquina (processing_timeout ou conversion_failed) e um error_message seguro. Um documento longo pode voltar ready com truncated=true; verifique essa marca.
Posso evitar a consulta?
Nos planos pagos, registre um webhook ou passe callback_url ao criar o job, e o serviço faz POST para você em ready ou error para que você não precise consultar.
Funciona com Node ou outras linguagens?
Sim. É uma API HTTPS simples, então qualquer linguagem funciona. Acima há um exemplo curto em Node, e o contrato completo está na especificação OpenAPI.
Como converto um arquivo local em vez de uma URL?
Faça POST dos bytes do arquivo como multipart/form-data com um campo file em /api/v2/jobs, em vez de um corpo JSON com url. Os passos de consultar e baixar são idênticos.
Posso converter muitos PDFs de uma vez?
Crie um job por arquivo e consulte-os em paralelo até o seu limite de espaços (3 no plano gratuito, mais nos pagos). Os planos pagos adicionam um endpoint de criação em lote e webhooks para que você não consulte nada.
A saída é a mesma da extensão e do app web?
Sim. Cada superfície usa o mesmo motor de conversão, então a API retorna o mesmo Markdown que você obteria no navegador.
É gratuito?
O plano gratuito oferece 3 espaços, arquivos de 10 MB, um orçamento de tempo de 15 minutos e retenção de 1 hora. Os planos pagos ampliam todos os limites e adicionam webhooks e criação em lote.