turndown foi a mais popular entre as quatro bibliotecas testadas no snapshot de metadados, com 11.386 estrelas no GitHub. Nos quatro fixtures HTML em comum, ela gerou zero tabelas em Markdown com as configurações padrão e usou 24,6% mais tokens do que markdownify para os mesmos dados.
Todas as quatro recuperaram cada um dos probes de conteúdo. As diferenças estão totalmente no que acontece com a estrutura — e no custo que essa estrutura traz depois.
O que foi medido e em quais fixtures
Esta base de pesquisa já tinha um conjunto para markitdown com cinco fixtures HTML e strings de probe pré-registradas — strings exatas verificadas para sobrevivência, além de strings de boilerplate usadas para detectar elementos decorativos da página. A comparação agregada usa os quatro fixtures compartilhados pelas quatro conversoras: um catálogo de livraria, um site de citações, uma tabela de estatísticas de hóquei e o artigo da Wikipedia sobre web scraping. Um quinto fixture, Nothing but tables, é usado apenas como diagnóstico focado em tabelas e fica fora do agregado de 24,6%.
As quatro: turndown 7.2.4 (Node), markdownify 1.2.3, html2text 2025.4.15 e markitdown, cujas linhas publicadas são usadas como estão. Páginas: um catálogo de livraria, um site de citações, uma tabela de estatísticas de hóquei e o artigo da Wikipedia sobre web scraping.
Cada nome de métrica abaixo corresponde exatamente ao campo correspondente no próprio artefato do markitdown, então as linhas podem ser colocadas lado a lado sem que ninguém precise reconciliar definições diferentes da mesma coisa.
A tabela

| Conversor | Probes no corpo | Caracteres de saída | Tokens (o200k) | Bytes/token | Linhas de tabela em Markdown | Links |
|---|---|---|---|---|---|---|
| turndown | 16/16 | 95.188 | 26.236 | 3.63 | 0 | 611 |
| markdownify | 16/16 | 76.868 | 21.062 | 3.65 | 36 | 599 |
| html2text | 16/16 | 76.452 | 21.176 | 3.61 | 32 | 545 |
| markitdown | 16/16 | 76.995 | 21.336 | 3.61 | 36 | 598 |
Quatro fixtures — os mesmos que o markitdown também executou. Os números completos por fixture estão em fiveway-scores.json. Tokens contados com o200k_base; as linhas de tabela do markitdown foram recalculadas a partir do próprio Markdown armazenado, usando o mesmo contador aplicado aos demais.
A sobrevivência do conteúdo é empate. Todos os dezesseis probes do corpo, nos quatro fixtures, sobreviveram em todas as conversoras. Se a única pergunta é “o texto vai passar?”, qualquer uma das quatro responde que sim.
A estrutura não é empate. Nos quatro fixtures compartilhados, markdownify e markitdown geram 36 linhas de tabela em Markdown; html2text gera 32; turndown não gera nenhuma. No diagnóstico separado centrado apenas em tabelas, markdownify gerou 62 linhas e html2text 59; essas linhas não entram no agregado acima.
O custo em tokens é 24,6% maior no turndown, e o motivo não são as tabelas. Eu achava que fosse, mas os números por fixture contam outra história — veja abaixo.
O que o turndown faz com uma tabela
Aqui está o fixture de estatísticas de hóquei, com as mesmas linhas, em três formatos.
turndown:

Team Name
Year
Wins
Losses
Boston Bruins
1990
44
24
markdownify:
| Team Name | Year | Wins | Losses | ... |
| --- | --- | --- | --- | --- |
| Boston Bruins | 1990 | 44 | 24 | ... |
html2text:
Team Name | Year | Wins | Losses | ...
---|---|---|---|---
Boston Bruins | 1990 | 44 | 24 | ...
Todo valor sobrevive à conversão do turndown, por isso ele marca 16/16 nos probes. O que não sobrevive é a qual coluna cada valor pertence. Leia a saída do turndown e 44 vira apenas um número em uma linha; não dá para recuperar que ele representa as vitórias do Boston sem contar posições e torcer para que nenhuma célula esteja vazia. Neste fixture, algumas células estão vazias, então contar posições também não funciona.
Para um modelo lendo a saída, essa é a diferença entre uma tabela sobre a qual ele consegue responder perguntas e uma lista de números que ele vai chutar.
Isso não é exatamente um defeito, mas sim um limite documentado — o núcleo do turndown não trata tabelas, e o turndown-plugin-gfm existe justamente para adicioná-las. Mas a instalação padrão não inclui esse plugin, e 11.386 estrelas sugerem que muita gente usa o pacote sem ele.
De onde realmente vem a diferença de tokens
Escrevi o parágrafo acima acreditando que a diferença de 24,6% em tokens vinha das tabelas achatadas aparecendo como caracteres. Depois olhei por fixture e vi que não era isso.
| Fixture | turndown tokens ÷ markdownify tokens |
|---|---|
| Site de citações (sem tabelas) | 0,99× |
| Catálogo de livraria | 1,06× |
| Estatísticas de hóquei (uma tabela grande) | 1,37× |
| Wikipedia (majoritariamente texto, 9 linhas de tabela) | 1,29× |
| Só tabelas | 0,78× |
No fixture que é só tabelas, o turndown é 22% mais barato — porque a estrutura com pipes também consome tokens, e o turndown não gera nada disso. Achatar uma tabela, por si só, não gera penalidade de tokens.
O fixture da Wikipedia representa 74% do total e tem nove linhas de tabela. A diferença de 15.378 caracteres não pode ser culpa das tabelas. É isto:
(function(){var className="client-js vector-feature-language-in-header-enabled…
.mw-parser-output cite.citation{font-style:inherit;word-wrap:break-word}…
(RLQ=window.RLQ||[]).push(function(){mw.config.set({"wgHostname":"mw-web…
turndown não remove conteúdo de <script> e <style>. markdownify e html2text removem. Contando marcadores que só aparecem dentro desses elementos: a saída do turndown carrega 10 marcadores de script e 84 de style ao longo dos fixtures; os outros dois têm zero de cada. Na página da Wikipedia, oito linhas de JavaScript inline e CSS do MediaWiki respondem por 14.644 caracteres — 95% de toda a diferença (script-style-stripping.json).
Essa é a descoberta que eu realmente levaria em conta. Uma tabela achatada é um problema de estrutura que você consegue enxergar. Um bloco de configuração JavaScript no seu Markdown é custo puro, sem informação útil alguma, e em uma página real ele supera com folga todo o resto desta comparação.
html2text escreve tabelas que talvez você não reconheça
html2text marcou 32 linhas, enquanto markdownify e markitdown marcaram 36, e a primeira versão do meu contador atribuiu a ele 1.
O problema era a minha regra de contagem, não a biblioteca. html2text emite Team Name | Year | Wins sem pipes no começo e no fim — um formato comum de tabela em Markdown, mas invisível para uma regex que exige ^\|.*\|$. Eu tinha escrito essa regex, executado a verificação e estava pronto para dizer que o html2text não faz tabelas.
Faz, sim. O contador corrigido usa uma heurística: uma sequência de linhas consecutivas com pipes e uma linha separadora no meio. Com essa regra, html2text vai de 1 para 32. Isso não é um parser completo de Markdown, então os totais devem ser lidos como medições sob um contador documentado, e não como resultado universal de renderização.
Vale saber se você pós-processa o Markdown com suas próprias regex: duas dessas quatro bibliotecas emitem pipes externos e uma não.
A licença que ninguém menciona
| Conversor | Licença | Instalação | Importação fria | Stars | Último lançamento |
|---|---|---|---|---|---|
| turndown | MIT | 3 pacotes npm, 8.8 MiB | 0.056 s | 11.386 | 2026-04-03 |
| markdownify | MIT | 5 pacotes, 1.8 MiB | 0.046 s | 2.235 | 2026-06-30 |
| html2text | GPL-3.0-ou-posterior | 1 pacote, 0.2 MiB | 0.077 s | 2.168 | 2025-04-15 |
| markitdown | Ver os metadados do pacote | Não medido nesta execução | Não medido | — | — |
install-and-import.json. Cada biblioteca foi instalada em seu próprio ambiente vazio. As licenças foram confirmadas em três fontes: os metadados do registry, o repositório no GitHub e o arquivo METADATA do pacote instalado, que diz License-Expression: GPL-3.0-or-later.
A biblioteca mais leve nesta comparação de instalação — 1 pacote, 0,2 MiB — é GPL-3.0-ou-posterior. Se isso afeta ou não um projeto depende de como o software é combinado e distribuído. Trate isso como um ponto de verificação para quem cuida da licença; este artigo não é aconselhamento jurídico. markitdown aparece como não medido aqui porque sua instalação e licença não foram capturadas por este artefato específico.
Essa troca é fácil de ignorar porque a licença é a única propriedade que não aparece em um benchmark.
As três são drasticamente mais leves do que as bibliotecas de extração de artigos na mesma categoria — essas variam de 21 a 70 MiB. Uma conversora é algo bem menor que uma extratora, e vale separá-las no orçamento de dependências.
Dois fatores de confusão que precisei corrigir antes de esta tabela ficar verdadeira
Os números acima são a terceira versão. As duas primeiras estavam erradas de maneiras que valem ser nomeadas, porque ambas são fáceis de reproduzir.
Cinco fixtures contra quatro. markitdown executou quatro destes cinco arquivos; os outros três executaram todos os cinco. Somar cada ferramenta no seu próprio conjunto fez markdownify parecer ter 98 linhas de tabela contra 36 do markitdown e deu a impressão de uma diferença de capacidade. Nos mesmos quatro, o resultado é 36 contra 36 — empate exato. O quinto fixture é justamente o mais pesado em tabelas, então o erro aconteceu na pior direção possível, inflando os novos participantes frente ao incumbente em quase três vezes.

Dois contadores, uma coluna. As md_table_rows publicadas pelo markitdown vieram do próprio código dele, que eu não tinha lido. Comparar esse número com o meu poderia significar comparar dois contadores, e não duas conversoras. A saída em Markdown fica armazenada em disco, então a correção foi rodar um único contador sobre os quatro — e, quando fiz isso, a recontagem do markitdown bateu exatamente com o número publicado por fixture (0, 0, 27, 9). As definições estavam de acordo; eu só não poderia saber disso sem conferir.
Nenhum desses erros apareceria olhando apenas a saída. Os dois produziriam uma tabela errada, mas cheia de confiança.
Quem deve usar o quê
Vai alimentar um modelo ou armazenar conteúdo estruturado de páginas como estas? Comece com markdownify. Ele empata com o markitdown na contagem de linhas de tabela emitidas sob este contador, fica no grupo de menor custo em tokens, é MIT e instala em 1,8 MiB. Valide com os formatos de página do seu caso antes de padronizar.
Seu orçamento de dependências é medido em kilobytes e você não vai distribuir o software? html2text. Um pacote, 0,2 MiB, tabelas intactas. Confira primeiro a questão da GPL e observe que o último lançamento foi em abril de 2025.
Já trabalha numa stack Node? turndown, junto com turndown-plugin-gfm — e remova <script> e <style> do HTML antes de passar o conteúdo adiante, porque o turndown não faz isso. Essas duas omissões custam um quarto a mais de tokens e destroem a estrutura da tabela, e nada disso aparece se você não olhar a saída.
Já converte outros formatos de documento? markitdown lida com PDF, Office e outros formatos, e sua saída em HTML compete bem com as conversoras dedicadas. Ter uma única dependência em vez de duas tem seu valor.
Onde uma API gerenciada se encaixa
Todas essas quatro soluções trabalham com HTML que você já tem. Nenhuma busca a página, renderiza JavaScript ou lida com camada anti-bot — e, para muitos alvos reais, essa é a parte mais difícil.
Nossa própria stack de desenvolvedores na Thunderbit cobre esse lado. POST /distill recebe uma URL e devolve Markdown limpo, pronto para LLM, com renderização e busca já tratadas; POST /extract devolve JSON estruturado com correspondência de schema via IA, usando o JSON Schema que você fornecer — ou seja, um formato de saída diferente, em linhas, em vez de uma tabela Markdown que depois você teria de interpretar. Ambos podem ser acessados por um servidor MCP e por CLI (npx @thunderbit/thunderbit-cli). Os preços estão na página de preços da Thunderbit.
A comparação honesta: se você já tem o HTML e quer Markdown, markdownify é gratuito e faz o trabalho muito bem, e esta tabela mostra quais concorrentes também fazem. Se você está coletando as páginas ou quer linhas estruturadas em vez de texto corrido, isso é outra compra.
Para o panorama mais amplo, nosso resumo de APIs de web scraping cobre opções hospedadas e o pilar de scrapers open source cobre as autohospedadas. Converter HTML em Markdown em Python é o guia prático, e o que o llms.txt tenta padronizar mostra para onde toda essa categoria está caminhando.
Experimente a Thunderbit para extração de dados da web
Veredito
Para esta carga de trabalho com quatro fixtures, markdownify é a melhor escolha padrão: a mesma contagem de linhas de tabela emitidas que markitdown sob o contador compartilhado, uma contagem de tokens dentro de 1,3% das outras conversoras eficientes, licença MIT e instalação de 1,8 MiB.
A diferença entre popularidade e comportamento medido é a descoberta aqui. turndown é uma excelente biblioteca, instalada por muita gente sem o plugin que a faz lidar com tabelas, e o custo disso aparece como um quarto a mais de tokens e uma estrutura de tabela que simplesmente deixa de existir. Nenhum desses números aparece até você contá-los.
Se for levar uma coisa daqui: verifique o que sua conversora faz com uma tabela antes de confiar a saída a um modelo. Três dessas quatro fazem algo sensato. A mais popular não faz — a menos que você peça.
Experimente a Thunderbit para extração de dados da web Get Started Free
Perguntas frequentes
O turndown realmente não suporta tabelas?
O núcleo dele não suporta. As tabelas vêm do turndown-plugin-gfm, um pacote separado, e o npm install turndown padrão não o inclui. Sem o plugin, cada célula sobrevive como um parágrafo independente — os valores estão todos lá, mas a relação entre linhas e colunas não. Nos quatro fixtures isso resultou em zero linhas de tabela em Markdown e 24,6% mais tokens do que markdownify para o mesmo conteúdo.
Por que o html2text parecia não ter tabelas no começo?
Porque meu contador exigia pipes no começo e no fim, e o html2text não os emite. Team Name | Year | Wins é Markdown válido e renderiza corretamente; só é um estilo diferente de | Team Name | Year |. O contador corrigido procura uma sequência de linhas com pipes e uma linha separadora, como um parser faria, e o html2text vai de 1 linha para 32. Se você pós-processa Markdown com suas próprias regex, é essa diferença que vai te pegar.
A GPL do html2text é um problema real?
Depende de como você combina e distribui o software. GPL-3.0-ou-posterior pode gerar obrigações que a MIT não gera, então envolva quem cuida de licenciamento antes de escolhê-lo para um produto distribuído. Isto é um ponto de conformidade, não aconselhamento jurídico; a identidade da licença foi confirmada nos metadados do registry, no repositório e no METADATA do pacote instalado.
Essas contagens de tokens valem para outras páginas?
A diferença de 24,6% vem principalmente do turndown manter conteúdo de <script> e <style>, então ela escala conforme a página contém mais desses blocos — alta em uma página moderna de CMS, quase zero em uma página estática. As tabelas puxam para o outro lado: no fixture que é só tabelas, o turndown ficou 22% mais barato, porque não emite a estrutura com pipes. Bytes por token ficaram entre 3,61 e 3,65 em todas as quatro, então a densidade de saída é a mesma; o que muda é a quantidade. Meça seu próprio corpus se esse número importar para o orçamento.
O que não foi testado aqui?
Variedade do mundo real — quatro fixtures são quatro fixtures. Listas aninhadas, listas de definição, notas de rodapé e matemática. HTML malformado, que historicamente é onde as conversoras mais divergem. Voltar do Markdown para HTML. docling, que tem os mesmos fixtures no disco, mas cuja execução publicada não reporta esses campos, então ele fica ausente em vez de estimado. E configuração: html2text foi executado com body_width=0, porque o padrão de 78 quebra automaticamente cada linha, o que teria alterado todos os caracteres e todas as contagens de tokens desta tabela.


