MarkItDown hamnar ofta i samma fack som web scrapers, men det är fel. Den har ingen crawler, ingen JavaScript-motor och inget sätt att hämta en URL och rensa bort sidans boilerplate. Det den gör är att ta bytes du redan har — en PDF, ett Word-dokument, ett kalkylblad, en presentation — och göra om allt till Markdown som en språkmodell kan läsa.
Jag ägnade ett par veckor åt att köra Microsofts MarkItDown genom ett batteri av riktiga dokument på en enda Mac, poängsatte varje tabell mot ett manifest jag skrev före körningen och mätte tiden för varje konvertering. Kort version: på ren input är den snabb och trogen originalet, paketeringen gömmer en 73 MB stor maskininlärningsruntime som du inte bad om, och tabellerna går sönder på sätt som klarar testet "överlevde texten?" men faller på testet "hamnade datan i rätt kolumn?". Här är hela bilden, med siffrorna.
Vad MarkItDown faktiskt är
MarkItDown är ett Python-verktyg från Microsoft som konverterar filer och Office-dokument till Markdown optimerat för LLM:er. Peka det mot en PDF, en .docx, en .xlsx, en .pptx, en bild, en HTML-fil eller några andra format, så får du tillbaka Markdown. Det går att använda på tre sätt: via CLI (markitdown file.pdf -o out.md, eller med input från stdin), via Python-API (MarkItDown().convert(...)) och via en valfri MCP-server för agentflöden.

Det viktigaste att förstå är vad det inte gör, eftersom README:n inte påstår det och jag bekräftade det i testerna: ingen crawling, ingen JS-rendering, inget följande av länkar, ingen paginering och ingen main-content-extraktion i stil med readability-verktyg. Det här är en konverterare för hela dokument. Du tar med bytesen; den normaliserar dem. Den skillnaden avgör om verktyget hör hemma i din stack eller inte, så jag kommer återkomma till den.
Själva repot är tungviktare enligt GitHubs fåfängestatistik — 165 282 stjärnor och 11 790 forks i mitten av juli 2026, MIT-licensierat, med senaste releasen (v0.1.6) ute 2026-05-26. Stjärnantalet säger dock mer om att det är ett Microsoft-repo som rider på allmän LLM-iver än om konverteringsmotorns mognad. Det finns också 833 öppna ärenden, och flera av dem är relevanta för dig innan du installerar det (mer om det nedan).
HTML till Markdown: snabbt, komplett och med boilerplate med på köpet
Eftersom resten av min scraper-recensionsserie använder samma fyra webb-fixtures matade jag MarkItDown med identiska lokala HTML-filer — inte för att betygsätta det som scraper, utan för att se hur bra HTML-till-Markdown-konverteringen är. På välstrukturerade sidor är den faktiskt riktigt bra.
Alla fyra sidor konverterades med basinstallationen, utan extra tillägg, och varje testpunkt i sidans huvudtext överlevde. Wikipedia-artikeln "Web scraping" (226 KB) kom ut med sin rubrikstruktur speglad — en h1, sju h2:or och tolv h3:or, vilket matchar artikelns verkliga avsnitt — och 418 länkar bevarade som korrekta [text](url). Hockey-statistiktabellen med 26×9 rutor på Scrape This Site forms page blev en ren GFM-pipetabell med 27 rader (rubrik + separator + 26 datarader), inklusive tomma celler. Hastigheten var inget problem här: medianen låg på 48 ms för den lilla quotes-sidan upp till 352 ms för Wikipedia-sidan på 226 KB.
Här kommer haken, och det är ett designval snarare än en bugg. MarkItDown rensar inte bort boilerplate. Den konverterar hela <body>, så sidans navigationsdelar följer med — och resterna växer med hur mycket chrome sidan har.
| Sida | Utdata-tecken | Rubriker (h1/h2/h3) | Länkar | Chrome-rader |
|---|---|---|---|---|
| Books to Scrape | 10,478 | 1 / 0 / 0 | 94 | 0.6% (1/159) |
| Quotes to Scrape | 2,973 | 1 / 1 / 0 | 55 | 1.2% (1/86) |
| ScrapeThisSite forms | 3,385 | 1 / 0 / 0 | 31 | 6.7% (5/75) |
| Wikipedia Web scraping | 60,159 | 1 / 7 / 12 | 418 | 12.4% (42/338) |
På Books-hemsidan, som nästan saknar chrome, är 0,6% av utdata-raderna chrome. På Wikipedia är det 12,4% — 42 av 338 icke-tomma rader är "jump to content", "toggle the table of contents", "22 languages", "retrieved from", cookie- och licensfötter. Wikipedias underhållsbanderoller ("This article needs additional citations") återges till och med troget som tvåkolumniga pipetabeller, vilket ger nio tabellrader på en sida utan någon riktig datatabell.
Inget av detta är MarkItDown som gör fel. Det är en hel-dokument-konverterare, inte en readability-extraherare: trogen HTML-till-Markdown är ett annat jobb än ren artikelutvinning. Trafilatura- och Firecrawl-liknande verktyg försöker bara returnera huvudinnehållet; MarkItDown returnerar hela sidan. Under huven tar dess _html_converter.py bort <script> och <style>, och skickar sedan hela body till markdownify-biblioteket — ingen heuristik för huvudinnehåll någonstans i kedjan. Om du bara vill ha artikeln är det här fel lager.
Hemmaplanen: PDF, DOCX, XLSX, PPTX
Dokument är vad MarkItDown är byggt för. Jag körde det mot riktiga offentliga filer — en arXiv-artikel med textlager, Bitcoin-whitepapret, en bildbaserad skannad PDF som jag renderade så att den hade noll text, samt DOCX/XLSX/PPTX-filerna från MarkItDowns egen testsvit (försedda med UUID:er så att jag kunde upptäcka tyst innehållsförlust).
| Dokument | Input | Utdata-tecken | Tester | Median tid | Anteckningar |
|---|---|---|---|---|---|
| arXiv 1706.03762 (PDF med textlager) | 2.2 MB | 40,174 | 7/7 | 3.7 s (warm) | titel, "Transformer", "BLEU", "References" alla närvarande |
| Bitcoin whitepaper (9 s PDF) | 184 KB | 22,485 | 6/6 | 1.4 s | "Satoshi Nakamoto", "proof-of-work", "Conclusion" närvarande |
| Skannad PDF (inget textlager) | 89 KB | 0 | 0/4 | 15 ms | tom utdata, inget fel, ingen OCR |
| DOCX (test.docx) | 136 KB | 4,651 | — | 70 ms | rubriker + GFM-tabell; inbäddade UUID:er överlever |
| DOCX med ekvationer | 15 KB | 240 | — | 101 ms | Office Math bevaras som LaTeX |
| XLSX (test.xlsx) | 12 KB | 808 | — | 57 ms | varje blad → ## SheetName + GFM-tabell |
| PPTX (test.pptx) | 278 KB | 2,047 | — | 52 ms | markörer för bildnummer, tabeller, diagram → tabell |
Textåtervinningen på PDF:erna med textlager var utmärkt — 7 av 7 förregistrerade testpunkter på arXiv-artikeln "Attention Is All You Need", 6 av 6 på Bitcoin whitepaper — och ingen av Office-filerna tappade en enda UUID-sentinel, så ingen tyst innehållsförlust i utvecklarnas egna regressions-fixtures. En fin, smal vinst: DOCX-vägen (via mammoth) bevarar Office Math-ekvationer som LaTeX och gör equations.docx till riktig $$...$$-matematik. Om du matar LLM:er med Word-dokument fulla av matematik är det en verklig, om än nischad, styrka som jag inte hittade beskriven någon annanstans.
Två saker på den här arenan förtjänar extra uppmärksamhet, eftersom de är de som mest sannolikt biter dig.
Den skannade PDF:en som försvinner
Mata MarkItDown med en bildbaserad PDF utan textlager, så får du tillbaka en tom sträng. Noll tecken, inget undantag, ingen varning — konverterad på ungefär 15 ms eftersom det inte finns något att extrahera. MarkItDowns PDF-väg är endast för textutvinning (pdfminer och pdfplumber under huven), och den levererar ingen OCR i kärninstallationen eller som något pip-extra.
Det spelar roll i batchjobb. En utvecklare som matar in en mapp med PDF:er där vissa är skannade får tyst tomma resultat för just de filerna, utan signal om att något hoppats över. Jag kontrollerade att testfilen inte var trasig genom att köra pdfminers extract_text direkt mot den — noll strippade tecken, inget textlager, bekräftat — så den tomma utdata är MarkItDowns verkliga beteende på en riktig skanning. Det här reproducerar ett länge öppet OCR-fallback-gap (#1268) som har följts upp upstream ett bra tag. Den dokumenterade vägen är den valfria Azure Document Intelligence-backenden eller ett plugin; inget av detta ingår i standardinstallationen.
PDF:er blir platt text, inte struktur
För båda PDF:erna med textlager producerade MarkItDown noll Markdown-markörer för rubriker. En PDF har inga semantiska rubrik-taggar, och MarkItDown gissar inte utifrån teckenstorlek, så varje rad hamnar på brödtextnivå. Textåtervinningen är hög; strukturen är platt.
Det här är inte bara min observation. Tredjeparts-benchmarks sätter MarkItDowns rubrikhierarki för PDF på runt 0,0 och tabelltroheten kring 0,27, långt under Doclings TableFormer-baserade 0,88 (se MarkItDown vs Docling vs Marker comparison och READoc benchmark). Mina fixtures reproducerar deras resultat, vilket stärker evidensen — mina siffror stämmer med en extern källa. Avvägningen som samma benchmarks pekar på är att MarkItDown kör ungefär 100× snabbare än Docling, vilket stämmer med mina sekunder-i-stället-för-minuter på dokument som ett layout-modellverktyg tuggar på i flera minuter. Slutsatsen: MarkItDown ger dig ren och snabb PDF-text; det ger dig inte PDF:ens struktur. Om rubriker och tabeller måste överleva är ett layout-modellverktyg som Docling eller Marker rätt lager.
Tabeller: innehållet överlever alltid, strukturen inte alltid
Tabeller är platsen där "överlevde texten?" och "går datan att använda?" skiljer sig åt, så jag byggde en matris med 13 fall — en <table> per fall, var och en poängsatt mot ett manifest skrivet före körningen — för att kartlägga exakt vilka former som håller och vilka som går sönder.

Huvudpoängen: MarkItDown tappade aldrig tabelldata. Alla 13 fall behöll 100% av sina förregistrerade tokens. Strukturell trohet däremot delade sig i tre lägen. Sju av tretton gav ett välformat GFM-grid (vanlig, header-colspan, 24 kolumner bred, utan rubrik, tomma celler, block-i-cell och höger-till-vänster-arabiska). Fyra blev ruffiga, eftersom Markdown inte har något begrepp för en cell som spänner över flera rader eller kolumner, så rowspan, colspan och trasiga källor ger korta rader. Och två var helt enkelt trasiga.
De två trasiga är värda att namnge. En nästlad tabell (en <table> inuti en <td>) plattas ut inline, dumpande sina egna pipes och separatorrad i föräldracellen och skapar en skräp-rad med 14 "kolumner". Och ett bokstavligt | inne i en cell escapes inte — celltexten a | b blir två kolumner, x || y blir tre — så en tabell med två kolumner skickar ut rader med två, tre och fyra kolumner, och varje Markdown-parser längre ner läser fel gränser. Märkligt nog escapes både asterisker och backticks i celler; bara pipes lämnas orörda. Rotorsaken är att MarkItDowns HTML-väg använder markdownifys standardhantering för tabeller, och dess egen subclass skriver om länkar, bilder och rubriker men inte tabellceller. Samma felklass kring pipe-escaping finns som ett öppet ärende för CSV-konverteraren (#2019), men den fixen påverkar inte HTML-vägen jag testade.
Det subtila fallet — fyndet jag helst skulle vilja att en data engineer såg — är rowspan. Fall t03 blir inte bara ruffigt; det feljusterar data tyst. En etikett med rowspan=2 ("Fruit") skrivs ut en gång, och raden under blir en kort tvåkolumnsrad (| Banana | 8 |), så "Banana" hamnar under kolumnen Group i stället för Item. Alla tokens finns där. En naiv konsument som "läser andra kolumnen" får fel värde. Det är den typen av bugg som klarar ett textöverlevnadstest men i tysthet korrumperar en datamängd.
Begränsningen kring span är i sig ett känt, spårat designval (#1211, #1248) — ett platt GFM-pipnät kan verkligen inte representera spans eller nästning, så konverteraren byter struktur mot fullständighet i innehållet. Det finns också bra beteenden i mixen: tabeller utan rubrik får en syntetisk tom rubrikrad (så inget datafält tyst upphöjs till rubrik), tomma celler bevaras och <caption> överlever som en textrad ovanför tabellen.
Installation och uppstart: skatten som ett "lättviktsverktyg" inte varnar dig för
Inget här överraskade mig mer, och det är här framen som "lättviktig Python-utility" i tysthet lovar för mycket.

Först: kör inte pip install 'markitdown[all]'. På Python 3.14 backar den då tyst hela vägen till markitdown 0.0.2 — en två år gammal release — vilket jag reproducerade live i en ren virtuell miljö. När man pinnade versionen blev orsaken tydlig: pip install 'markitdown[all]==0.1.6' ger fel eftersom [all]-extra:n låser youtube-transcript-api~=1.0.0, och på nuvarande PyPI är varje build i det intervallet spärrad för Python <3.14, medan de enda 3.14-kompatibla byggena ligger utanför låsningen. Resolvern backar därför hela vägen till den sista releasen vars beroenden går att uppfylla. Det här matchar ett öppet upstream-ärende (#2179). Lösningen är enkel — pinna versionen och installera extras var för sig: pip install 'markitdown==0.1.6', sedan pip install 'markitdown[pdf,docx,pptx,xlsx,xls]==0.1.6'. Var och en av dessa fungerar utan problem; det är bara den kombinerade [all]-paketeringen som innehåller den förgiftade låsningen. (Den här fallgropen beror på Python-version — på Python 3.13 eller tidigare kanske spärren inte slår till, så [all] kan lösas annorlunda.)
För det andra: fotavtrycket. Basinstallationen är 161 MB (en tom virtuell miljö på 13 MB plus 148 MB). Av detta står onnxruntime (73 MB) och numpy (34 MB) tillsammans för 107 MB — 66% av hela basfotavtrycket — och båda dras in av ett enda hårt beroende: magika, Googles ML-detektor för filtyper. Så en textkonverterare levererar alltså en 73 MB stor ONNX-inferensruntime i basinstallationen innan du lägger till en enda dokument-extra. Lägg till dokument-extras så växer den virtuella miljön till 310 MB. Det här är mycket lättare än en headless browser-stack, men om du förväntade dig en "pip install och klart"-mikroutility bör du veta att en ONNX-runtime följer med.
För det tredje — och det här är den enda observationen i hela paketet som klarar varje novelty-check jag körde — även efter en ren installation kostar import markitdown ungefär 3,35 sekunder på den här maskinen. Kostnaden ligger nästan helt vid importtid: markitdown._markitdown importerar ivrigt hela konverterarregistret (2,56 s kumulativt, 76% av totalen), vilket drar in pandas (594 ms, via XLSX-konverteraren), python-pptx (427 ms), magika (354 ms) och requests (270 ms) — oavsett om du faktiskt konverterar något av dessa format. För en långlivad tjänst amorteras den kostnaden bort och spelar ingen roll. För ett CLI-anrop eller en serverless cold start är det en verklig per-process-skatt som etiketten "lättviktig utility" inte får dig att förvänta dig. (Rimlig brasklapp: detta är en enskild profilerad körning, behandlad som en observation, inte en fördelning över flera körningar.)

Skala: den kraschar inte, men budgetera CPU för PDF:er och RAM för kalkylblad
Jag körde fyra stora ämnen igenom, var och en i sin egen process så att toppminnet inte skulle påverkas av en tidigare körning. Inget kraschade. Kostnadsprofilen är dock ojämn.

| Ämne | Input | Utdata-tecken | Median tid | Topp-RSS Δ |
|---|---|---|---|---|
| NIST SP 800-53r5 (492-sidig PDF) | 5.9 MB | 1,625,365 | 192.5 s | +40 MB |
| XLSX 50,000 rader × 8 kolumner | 2.1 MB | 3,722,955 | 62.1 s | +374 MB |
| arXiv 1706.03762 (~15-sidig PDF) | 2.2 MB | 40,174 | 12.6 s | +25 MB |
| XLSX 200 rader × 64 kolumner | 46 KB | 120,129 | 2.9 s | +22 MB |
Den 492 sidor långa NIST-PDF:en tog i median 192,5 sekunder — ungefär 3,2 minuter, eller 0,39 s/sida — eftersom pdfplumber kör formdetektering baserad på ordpositioner på varje sida. Topp-RSS låg kvar på +40 MB, så det är CPU-bundet, inte minnesbundet. Även den 15-sidiga arXiv-PDF:en tog 12,6 sekunder i en egen isolerad process, ungefär 3,4 gånger de 3,7 sekunder samma fil visade varm i min dokumentserie. Det gapet är kostnaden för kall process och bekräftar att det per-sida-arbete som driver tiden, inte rå filstorlek. Om du vill ha ett enda överförbart tal för den PDF:en, använd de isolerade 12,6 sekunderna.
Kalkylbladsvägen vänder på flaskhalsen. En 2,1 MB stor XLSX med 50 000 rader steg till +374 MB topp-RSS (och 3,7 miljoner utdata-tecken) eftersom konverteraren laddar hela bladet och bygger en stor Markdown-sträng. Så den praktiska tumregeln är rak: stora PDF:er, räkna med minuter av CPU; stora kalkylblad, räkna med hundratals MB RAM. Det här är siffror från en enda Mac-maskin med macOS arm64 och Python 3.14, och konstanterna per sida och per rad är plattformsspecifika — men formen (PDF är långsam och CPU-bunden, XLSX är minnestung, inget kraschar) är det som faktiskt går att föra över.
Var Thunderbit passar in — och var det inte gör det
Testa Thunderbit för webbdatastrahering
Det här är den jämförelse som lätt blir överdriven, så jag drar gränsen försiktigt. MarkItDown och Thunderbit löser närliggande problem, inte samma.
MarkItDown konverterar filer du redan har. Thunderbit hämtar sidan först. Thunderbits /distill-endpoint gör om en levande webbsida till ren Markdown redo för LLM:er — och hanterar JS-rendering, bot-skydd och dynamiskt innehåll som MarkItDown inte har någon mekanism för — medan dess /extract-endpoint returnerar schema-matchad strukturerad JSON, inte bara rå Markdown. För utvecklare exponeras det som ett API (POST /distill / POST /extract), en MCP-server och en CLI (npx @thunderbit/thunderbit-cli) ovanpå en AI-motor, samma motor som ligger bakom tillägget med över 100 000 användare.
Så de överlappar bara på en punkt — båda kan ge ut "LLM-redo Markdown" — men indata-domänen är olika: Thunderbits distill tar en URL på öppna webben, MarkItDown tar en lokal fil. De är inte utbytbara, och det tänker jag inte låtsas som. Den realistiska stacken använder båda: hämta och crawla webben med Thunderbit (eller en Firecrawl-liknande tjänst), och normalisera sedan de blandade lokala dokument du också har — PDF:er, presentationer och kalkylblad — med MarkItDown. Den ena hanterar nätverket; den andra hanterar dokumenthögen.
Fördelar och nackdelar
Styrkor
- Fullständig återgivning av brödtext på ren HTML (4/4 sidor), med rubrikträd och länkar troget bevarade
- Hög textåtervinning för PDF/DOCX (arXiv 7/7 tester, Bitcoin 6/6) och ingen tyst innehållsförlust i utvecklarnas egna Office-fixtures
- Office Math-ekvationer bevaras som LaTeX — en verklig nischvinst
- Kraschade aldrig vid någon teststorlek, upp till en 492-sidig PDF och en XLSX med 50k rader
- Enkelt att anropa: CLI,
convert(), piping via stdin och en valfri MCP-server - MIT-licensierat, aktivt underhållet av Microsoft, med responsiv ärendehantering
Svagheter
- Behåller boilerplate — upp till 12,4% chrome-rader på Wikipedia; inte en artikelutvinnare
- Tabeller går sönder vid spans, nästning och pipes i celler (2/13 trasiga, 4/13 ruffiga), och rowspan kan tyst flytta data till fel kolumn
- Skannade/bildbaserade PDF:er ger tom utdata utan OCR och utan felmeddelande
- PDF-utdata har ingen rubrikstruktur alls (stämmer med publika benchmarks)
- 161 MB basinstallation med en 73 MB ONNX-runtime; cirka 3,35 s kall import
[all]-extra backar tyst till en två år gammal 0.0.2 på Python 3.14
Vem bör använda det, och vem bör låta bli
Välj MarkItDown om du standardiserar en hög blandade lokala dokument — Word, Excel, PowerPoint, textlager-PDF:er — till Markdown för en LLM-pipeline, och du bryr dig mer om komplett text än om bevarad struktur. Som sista steg i ett batchjobb, när du matar modellen med ren text, är det snabbt, troget och gratis.
Hoppa över det, eller kombinera det med något annat, om ditt jobb är något av detta: du behöver bara huvudartikeln från en webbsida (använd ett readability- eller Firecrawl-liknande verktyg); du behöver att en PDF:s rubriker och tabeller överlever intakta (då är Docling eller Marker rätt område); eller så innehåller dina input skannade dokument som kräver OCR (då behöver du Azure-backenden eller ett helt annat verktyg). Och om du trodde att du letade efter en scraper — något som hämtar och crawlar — så är det här inte det alls.
Den preliminära poäng jag körde, på ett scraper-liknande rubric, landar MarkItDown på 60/100, och den låga totalen är en effekt av att betygsätta en konverterare med en crawlers prov. På sin egen hemmaplan är texttroheten hög; svagheterna är strukturella (tabeller, PDF-rubriker) och paketeringsmässiga (fotavtryck, import, [all]-fällan), inte textkvaliteten. Bedöm den för vad den är — en fil-till-Markdown-konverterare — så är det ett stabilt, välskött verktyg med några skarpa kanter du bör känna till innan du kopplar in det i produktion.
Vanliga frågor
Är MarkItDown en web scraper?
Nej. Den har ingen crawler, ingen JavaScript-rendering, inget följande av länkar och ingen paginering. Den konverterar filer och dokument du redan har — PDF, DOCX, XLSX, PPTX, bilder, HTML — till Markdown. Om du behöver hämta och crawla levande webbsidor ska du använda ett scraping-verktyg som Thunderbit eller Firecrawl; MarkItDown är steget efter, när redan hämtade eller lokala filer ska göras om till ren Markdown.
Varför installerar pip install markitdown[all] en gammal version?
På Python 3.14 låser [all]-extra:n youtube-transcript-api~=1.0.0, och varje build i det intervallet är spärrad för Python-versioner under 3.14. Resolvern kan inte uppfylla låsningen, så den backar tyst till markitdown 0.0.2, en två år gammal release. Lösningen är att pinna versionen och installera extras var för sig: pip install 'markitdown==0.1.6', och sedan lägga till 'markitdown[pdf,docx,pptx,xlsx,xls]==0.1.6'. Det här spåras som issue #2179.
Gör MarkItDown OCR på skannade PDF:er?
Inte i standardinstallationen. PDF-vägen är endast för textutvinning, så en bildbaserad PDF utan textlager ger en tom sträng — inget fel, ingen varning. OCR kräver den valfria Azure Document Intelligence-backenden eller ett plugin, och inget av detta följer med som standard. Det här är ett länge känt gap (issue #1268).
Hur bra hanterar MarkItDown tabeller?
Innehållsmässigt mycket bra — i mitt test med 13 fall behöll den 100% av tabelldatan i samtliga fall. Strukturellt beror det på formen: enkla, breda, rubriklösa och cell-tomma tabeller blir rena GFM-rutor, men rowspan och colspan blir ruffiga (och rowspan kan tyst flytta data till fel kolumn), nästlade tabeller plattas ut till skräp-rader, och bokstavliga pipe-tecken i celler escapes inte. Markdowns platta tabellformat kan helt enkelt inte representera spans eller nästning.
Är MarkItDown tillräckligt snabb för stora dokument?
Den kraschar inte på stora filer, men budgetera resurser efter typ. En 492-sidig PDF tog ungefär 3,2 minuter (cirka 0,39 s/sida) eftersom den gör per-sida-formdetektering, och den är CPU-bunden. Ett kalkylblad med 50 000 rader blev klart på ungefär en minut men använde +374 MB RAM eftersom det bygger en stor Markdown-sträng i minnet. För stora PDF:er: räkna med minuter av CPU. För stora kalkylblad: räkna med hundratals MB RAM.
Testa Thunderbit för webbdatastrahering Get Started Free


