Tutorial de Python

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.

Resposta breve

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.

Como fazer

Configure em quatro passos

1

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.

2

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.

3

Consulte até ready

Faça GET /api/v2/jobs/{id} até status ser ready ou error.

4

Baixe o Markdown

Faça GET /api/v2/jobs/{id}/download para o texto Markdown. Respeite truncated e pages.

Exemplo completo

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.

Deixe robusto

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.

Outras linguagens

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 frequentes

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.