La libreria HTML-to-Markdown più popolare non converte le tabelle

Ultimo aggiornamento il August 17, 2026
La libreria HTML-to-Markdown più popolare non converte le tabelle
Riepilogo AI
turndown era la più apprezzata tra le quattro librerie testate al momento dello snapshot dei metadati, con 11.386 stelle su GitHub. Sui quattro fixture HTML condivisi ha prodotto zero tabelle Markdown con le impostazioni predefinite del core e ha usato il 24,6% in più di token rispetto a markdownify a parità di input. Tutte e quattro hanno recuperato ogni probe di contenuto. Le differenze stanno interamente in ciò che accade alla struttura, e in quanto quella struttura ti costa a valle. Se stai alimentando un modello, o memorizzando contenuti strutturati da pagine come queste? Parti da markdownify. Con questo contatore è alla pari con markitdown nel numero di righe di tabella prodotte, sta nel gruppo a minor consumo di token, è MIT e si installa in 1,8 MiB.

turndown era la più apprezzata, tra le quattro librerie testate, al momento dello snapshot dei metadati, con 11.386 stelle su GitHub. Sui quattro fixture HTML condivisi ha prodotto zero tabelle Markdown con le impostazioni predefinite del core e ha usato il 24,6% in più di token rispetto a markdownify a parità di input.

Tutte e quattro hanno recuperato ogni probe di contenuto. Le differenze stanno tutte in quello che succede alla struttura, e in quanto quella struttura ti costa dopo.

Cosa è stato misurato, e su quali fixture

Questa base di ricerca aveva già un pacchetto per markitdown con cinque fixture HTML e stringhe probe registrate — stringhe esatte controllate per verificare la sopravvivenza, più stringhe boilerplate usate per intercettare i contenuti di contorno della pagina. Il confronto aggregato usa i quattro fixture condivisi da tutti e quattro i converter: un catalogo di libreria, un sito di citazioni, una tabella di statistiche hockey e l’articolo di Wikipedia sul web scraping. Una quinta fixture, Nothing but tables, viene usata solo come diagnostica pesante di tabelle ed è esclusa dall’aggregato del 24,6%.

I quattro: turndown 7.2.4 (Node), markdownify 1.2.3, html2text 2025.4.15 e markitdown, le cui righe pubblicate sono usate così come sono. Pagine: un catalogo di libreria, un sito di citazioni, una tabella di statistiche hockey e l’articolo di Wikipedia sul web scraping.

Ogni nome di metrica qui sotto corrisponde campo per campo al file di output di markitdown, così le righe si possono mettere una accanto all’altra senza dover far combaciare due definizioni della stessa parola.

La tabella

Measured results chart: Token output vs Markdown table rows

ConverterBody probesOutput charsTokens (o200k)Bytes/tokenMarkdown table rowsLinks
turndown16/1695,18826,2363.630611
markdownify16/1676,86821,0623.6536599
html2text16/1676,45221,1763.6132545
markitdown16/1676,99521,3363.6136598

Quattro fixture — quelli eseguiti anche da markitdown. I numeri completi per ogni fixture sono in fiveway-scores.json. I token sono contati con o200k_base; le righe di tabella di markitdown sono state ricontate dal suo Markdown salvato usando lo stesso contatore applicato agli altri.

La sopravvivenza del contenuto è un pareggio. Tutti e sedici i probe del corpo, nei quattro fixture, sono sopravvissuti in ogni converter. Se la tua unica domanda è “il testo passa?”, per tutti e quattro la risposta è sì.

La struttura non è un pareggio. Nei quattro fixture condivisi, markdownify e markitdown producono entrambi 36 righe di tabella Markdown; html2text ne produce 32; turndown non ne produce nessuna. Nel diagnostico separato solo per tabelle, markdownify ha prodotto 62 righe e html2text 59; queste righe non sono incluse nell’aggregato sopra.

Il costo in token è più alto del 24,6% per turndown, e il motivo non sono le tabelle. Pensavo fosse quello, ma i numeri per singola fixture dicono il contrario — vedi sotto.

Cosa fa turndown a una tabella

Ecco la fixture con le statistiche hockey, le stesse righe, in tre modi.

turndown:

System diagram: Core Table Paths Diverge

Team Name

Year

Wins

Losses

Boston Bruins

1990

44

markdownify:

| Team Name | Year | Wins | Losses | ... |
| --- | --- | --- | --- | --- |
| Boston Bruins | 1990 | 44 | 24 | ... |

html2text:

Team Name  |  Year  |  Wins  |  Losses  | ...
---|---|---|---|---
Boston Bruins  |  1990  |  44  |  24  | ...

Ogni valore sopravvive alla conversione di turndown, ed è per questo che ottiene 16/16 nei probe. Quello che non sopravvive è a quale colonna appartiene ciascun valore. Leggi l’output di turndown e 44 è solo un numero su una riga; non puoi ricostruire che sia il numero di vittorie dei Boston senza contare le posizioni e sperare che nessuna cella fosse vuota. In questa fixture alcune celle sono vuote, quindi contare le posizioni non funziona comunque.

Per un modello che legge l’output, è la differenza tra una tabella su cui può rispondere a domande e un elenco di numeri su cui dovrà tirare a indovinare.

Non si tratta tanto di un difetto quanto di un limite documentato — il core di turndown non gestisce le tabelle, e turndown-plugin-gfm esiste per aggiungerle. Ma l’installazione di default non lo include, e 11.386 stelle suggeriscono che molte persone stiano usando proprio il default.

Da dove arriva davvero il divario nei token

Avevo scritto il paragrafo sopra convinto che il gap di token del 24,6% fosse dovuto alle tabelle appiattite che si trasformavano in caratteri. Poi ho guardato i dati per fixture, e non è così.

Fixtureturndown tokens ÷ markdownify tokens
Quotes site (no tables)0.99×
Bookshop catalogue1.06×
Hockey statistics (one big table)1.37×
Wikipedia (mostly prose, 9 table rows)1.29×
Nothing but tables0.78×

Sulla fixture che è solo tabelle, turndown è più economico del 22% — perché anche l’impalcatura con i pipe costa token, e turndown non la emette proprio. Appiattire una tabella, da solo, non comporta una penalità in token.

La fixture di Wikipedia pesa il 74% del totale e contiene nove righe di tabella. Il suo divario di 15.378 caratteri non può essere dovuto alle tabelle. È questo:

(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 non rimuove il contenuto di <script> e <style>. markdownify e html2text sì. Contati tramite marker che compaiono solo all’interno di quegli elementi: l’output di turndown contiene 10 marker di script e 84 marker di style nei fixture; gli altri due ne hanno zero. Nella pagina di Wikipedia, otto righe di configurazione JavaScript inline e CSS di MediaWiki spiegano 14.644 caratteri — il 95% dell’intero divario (script-style-stripping.json).

Questa è la conclusione su cui agirei davvero. Una tabella appiattita è un problema di struttura che puoi vedere. Un blob di configurazione JavaScript dentro il tuo Markdown è puro costo, senza alcuna informazione, e su una pagina reale sovrasta tutto il resto di questo confronto.

html2text scrive tabelle che potresti non riconoscere

html2text ha totalizzato 32 righe mentre markdownify e markitdown ne hanno segnate 36, e la prima versione del mio contatore gli attribuiva 1.

Era una regola di conteggio mia, non della libreria. html2text emette Team Name | Year | Wins senza pipe iniziale e finale — una forma comune di tabella Markdown, ma invisibile a una regex che richiede ^\|.*\|$. Avevo scritto io quella regex, l’avevo eseguita e stavo per riportare che html2text non fa tabelle.

Invece le fa. Il contatore corretto usa un’euristica: una sequenza di righe consecutive che contengono pipe con una riga separatrice all’interno. Con questa regola, html2text passa da 1 a 32. Non è un parser Markdown completo, quindi i totali delle righe vanno letti come misure ottenute con un contatore documentato, non come risultati universali di rendering.

Da sapere se poi fai post-processing del Markdown con le tue regex: due di queste quattro librerie emettono le pipe esterne e una no.

La licenza di cui nessuno parla

ConverterLicenceInstallCold importStarsLast release
turndownMIT3 npm packages, 8.8 MiB0.056 s11,3862026-04-03
markdownifyMIT5 packages, 1.8 MiB0.046 s2,2352026-06-30
html2textGPL-3.0-or-later1 package, 0.2 MiB0.077 s2,1682025-04-15
markitdownSee its package metadataNot measured in this install runNot measured

install-and-import.json. Ogni libreria è stata installata in un proprio ambiente vuoto. Le licenze sono state verificate in tre punti: i metadati del registry, il repo GitHub e il file METADATA del pacchetto installato, che riporta License-Expression: GPL-3.0-or-later.

La libreria più leggera in questo confronto di installazione — un pacchetto, 0,2 MiB — è GPL-3.0-or-later. Se questo sia un problema per un progetto dipende da come il software viene combinato e distribuito. Consideralo un punto di controllo per chi gestisce la licenza; questo articolo non è consulenza legale. markitdown è mostrato come non misurato qui perché la sua installazione e la sua licenza non sono state catturate da questo specifico artifact.

Questo compromesso è facile da perdere perché la licenza è l’unica proprietà che non compare in un benchmark.

Tutte e tre sono molto più leggere delle librerie di estrazione articoli nella stessa categoria — quelle arrivano a 21-70 MiB. Un converter è una cosa molto più piccola di un extractor, e vale la pena tenerli distinti nel budget delle dipendenze.

Due fattori di confusione che ho dovuto correggere prima che questa tabella fosse vera

I numeri qui sopra sono la terza versione. Le prime due erano sbagliate in modi che vale la pena nominare, perché entrambi sono facili da riprodurre.

Cinque fixture contro quattro. markitdown ha eseguito quattro di questi cinque file; gli altri tre hanno eseguito tutti e cinque. Sommare ogni strumento sul proprio set dava a markdownify 98 righe di tabella contro le 36 di markitdown e faceva sembrare la cosa un divario di capacità. Sui medesimi quattro, invece, è 36 contro 36 — un pareggio perfetto. La quinta fixture è quella pesante di tabelle, quindi il fattore di confusione andava nella direzione peggiore possibile, gonfiando i newcomer rispetto al tool già presente di quasi tre volte.

System diagram: Make the Comparison Comparable

Due contatori, una colonna. Il md_table_rows pubblicato da markitdown proveniva dal suo codice, che non avevo letto. Confrontare quel numero con il mio avrebbe potuto significare confrontare due contatori e non due converter. Il suo output Markdown è salvato su disco, quindi la correzione è stata eseguire un unico contatore su tutti e quattro — e quando l’ho fatto, il ricontrollo di markitdown è uscito esattamente pari al valore pubblicato per fixture (0, 0, 27, 9). Le definizioni coincidevano; semplicemente non potevo saperlo senza verificare.

Nessuno dei due errori sarebbe stato visibile nell’output. Entrambi avrebbero prodotto una tabella convincente ma sbagliata.

Chi dovrebbe usare cosa

Se stai alimentando un modello, o memorizzando contenuti strutturati da pagine come queste? Parti da markdownify. Con questo contatore è alla pari con markitdown nel numero di righe di tabella prodotte, sta nel gruppo a minor consumo di token, è MIT e si installa in 1,8 MiB. Verificalo sulle forme reali delle tue pagine prima di standardizzarlo.

Se il budget delle dipendenze si misura in kilobyte e non devi distribuire il software? html2text. Un pacchetto, 0,2 MiB, tabelle intatte. Controlla prima la questione GPL e nota che l’ultima release è di aprile 2025.

Se sei già in uno stack Node? turndown, con turndown-plugin-gfm installato insieme — e rimuovi <script> e <style> dall’HTML prima di passarlo, perché turndown non lo farà. Quei due soli elementi aggiungono un quarto di token in più e ti fanno perdere la struttura della tabella, e non te ne accorgi finché non guardi l’output.

Se stai già convertendo altri formati di documento? markitdown gestisce PDF, Office e altro ancora, e il suo output HTML è competitivo con i converter dedicati. Avere una sola dipendenza invece di due qualcosa vale.

Dove si colloca un’API gestita

Tutti e quattro questi strumenti lavorano sull’HTML che hai già. Nessuno scarica una pagina, renderizza JavaScript o gestisce un anti-bot layer — e per molti target reali, quella è la metà più difficile.

Il nostro stack per sviluppatori su Thunderbit copre proprio quel lato. POST /distill prende un URL e restituisce Markdown pulito, pronto per LLM, con rendering e fetch gestiti; POST /extract restituisce JSON strutturato, allineato a uno schema AI, rispetto a uno JSON Schema fornito da te, quindi con una forma di output diversa — righe invece di una tabella Markdown che dovresti poi parsare. Entrambi sono accessibili da un server MCP e da una CLI (npx @thunderbit/thunderbit-cli). I prezzi sono nella pagina prezzi di Thunderbit.

Il confronto onesto: se hai già l’HTML e vuoi Markdown, markdownify è gratuito e fa bene il suo lavoro, e questa tabella ti dice quali rivali fanno altrettanto. Se devi recuperare le pagine, o vuoi righe strutturate invece di prosa, si tratta di un acquisto diverso.

Per il panorama più ampio, il nostro panoramica delle API di web scraping copre le opzioni hosted e il pilastro degli scraper open source quelle self-hosted. Convertire HTML in Markdown in Python è la guida pratica, mentre cosa sta cercando di standardizzare llms.txt spiega dove sta andando l’intera categoria.

Prova Thunderbit per l’estrazione di dati web

Verdetto

Per questo workload su quattro fixture, markdownify è il default più solido: stesso numero di righe di tabella prodotte di markitdown secondo il contatore condiviso, un conteggio di token entro l’1,3% rispetto agli altri converter efficienti, licenza MIT e installazione da 1,8 MiB.

Quel divario tra popolarità e comportamento misurato è il vero risultato. turndown è una libreria eccellente che moltissime persone hanno installato senza il plugin che la fa gestire le tabelle, e il costo di questa scelta si vede in un quarto di token in più e in una struttura tabellare che non esiste più. Nessuno dei due numeri appare da nessuna parte finché non li conti.

Se devi ricordarti una sola cosa: verifica cosa fa il tuo converter a una tabella prima di affidarti al suo output per un modello. Tre di questi quattro fanno qualcosa di sensato. Il più popolare no, a meno che tu non glielo chieda.

Prova Thunderbit per l’estrazione di dati web Get Started Free

FAQ

turndown davvero non supporta le tabelle? Il suo core no. Le tabelle arrivano da turndown-plugin-gfm, un pacchetto separato, e il semplice npm install turndown non lo include. Senza il plugin, ogni cella sopravvive come paragrafo separato — i valori ci sono tutti, i rapporti tra righe e colonne no. Su quattro fixture questo ha prodotto zero righe di tabella Markdown e il 24,6% di token in più rispetto a markdownify a parità di contenuto.

Perché all’inizio html2text sembrava non avere tabelle? Perché il mio contatore richiedeva pipe iniziali e finali e html2text non le emette. Team Name | Year | Wins è Markdown valido e si renderizza correttamente; è semplicemente uno stile diverso da | Team Name | Year |. Il contatore corretto cerca una sequenza di righe con pipe e una riga separatrice, come farebbe un parser, e html2text passa da 1 riga a 32. Se fai post-processing del Markdown con regex tue, questa è la differenza che ti colpirà.

La GPL di html2text è davvero un problema? Dipende da come combini e distribuisci il software. GPL-3.0-or-later può creare obblighi che MIT non crea, quindi coinvolgi chi gestisce la licenza prima di sceglierlo per un prodotto distribuito. Questo è un controllo di conformità, non un consiglio legale; l’identità della licenza è stata confermata nei metadati del registry, nel repository e nel METADATA del pacchetto installato.

Questi conteggi dei token sono significativi anche per altre pagine? Il divario del 24,6% è dovuto soprattutto al fatto che turndown conserva il contenuto di <script> e <style>, quindi scala con la quantità di quel contenuto in una pagina — molto su un sito CMS moderno, quasi zero su una pagina statica. Le tabelle spostano la situazione nella direzione opposta: sulla fixture composta solo da tabelle turndown è risultato più economico del 22%, perché non emette l’impalcatura con i pipe. I byte per token sono rimasti tra 3,61 e 3,65 per tutti e quattro, quindi la densità dell’output è identica ovunque e cambia solo la quantità. Misura il tuo corpus se quel numero conta per il budget.

Cosa non è stato testato qui? La varietà del mondo reale — quattro fixture sono pur sempre quattro fixture. Liste annidate, liste di definizione, note a piè di pagina e formule matematiche. HTML malformato, dove storicamente i converter divergono di più. Il round-trip del Markdown verso HTML. docling, che ha gli stessi fixture su disco ma il cui run pubblicato non riporta questi campi, quindi è assente invece che stimato. E la configurazione: html2text è stato eseguito con body_width=0 perché il default di 78 manda a capo forzatamente ogni riga, il che avrebbe cambiato ogni singolo carattere e conteggio di token in questa tabella.

Ke
Ke
CTO di Thunderbit | Senior Data Scientist ed esperto di ML Con quasi un decennio di esperienza nel machine learning e nella data science, Ke Shen è un ex studente della Columbia University ed ex Senior Data Scientist presso Walmart Labs. Grazie a una profonda competenza, riconosciuta dai suoi pari, in Python, R, Java e statistica, condivide insight collaudati sul passaggio di algoritmi AI complessi dalla teoria a un'architettura pronta per la produzione.
Indice
Thunderbit · Agente AI per dati web

Estrai dati da qualsiasi pagina in 1 clic

Scelto da oltre 250.000 utenti
piano gratuito disponibile
Dalla pagina web al foglio di calcolo
Descrivi ciò che ti serve — l'agente AI di Thunderbit lo estrae ed esporta in Excel, Google Sheets, Airtable o Notion. Puoi iniziare gratis.
Chrome Store Rating
PRODUCT HUNT#1 Product of the Week