Apache Tika-review: het leest de bytes, niet de bestandsnaam — totdat het Markdown tegenkomt

Laatst bijgewerkt op August 14, 2026
Apache Tika-review: het leest de bytes, niet de bestandsnaam — totdat het Markdown tegenkomt
AI-samenvatting
Apache Tika is de toolset van de Apache Software Foundation voor het parsen van documenten: geef het een bestand van bijna elk type en je krijgt er platte tekst plus een genormaliseerde metadata-dictionary voor terug. De project-README claimt meer dan duizend ondersteunde bestandstypen, en Tika bereikt dat door zelf de specialistische bibliotheken mee te bundelen — PDFBox voor PDF’s, Apache POI voor Office-documenten, jsoup voor HTML, een ODF-reader voor ODT — zodat het geheel als één grote jar wordt geleverd, zonder dat er bij het parsen nog iets hoeft te worden opgehaald. In een datapipeline is het de weinig glamoureuze eerste stap: het onderdeel vóór een zoekindex, een e-discovery-reviewset of een LLM-corpus dat een heterogene stapel bestanden omzet in iets uniforms.

Apache Tika is de toolset van de Apache Software Foundation voor het parsen van documenten: geef het een bestand van bijna elk type en je krijgt er platte tekst plus een genormaliseerde metadata-dictionary voor terug. De project-README claimt meer dan duizend ondersteunde bestandstypen, en Tika bereikt dat door zelf de specialistische bibliotheken mee te bundelen — PDFBox voor PDF’s, Apache POI voor Office-documenten, jsoup voor HTML, een ODF-reader voor ODT — zodat het geheel als één grote jar wordt geleverd, zonder dat er bij het parsen nog iets hoeft te worden opgehaald. In een datapipeline is het de weinig glamoureuze eerste stap: het onderdeel vóór een zoekindex, een e-discovery-reviewset of een LLM-corpus dat een heterogene stapel bestanden omzet in iets uniforms. Eigenlijk maar twee taken: uitzoeken wat een byte stream is en daar vervolgens de tekst en metadata uit halen.

Het is de minst veeleisende tool die ik in lange tijd heb opgezet. Eén jar, java -jar tika-app-3.3.2.jar --text file.pdf, geen configuratiebestand, geen modelgewichten, geen post-installstap, en het draaide probleemloos op een cutting-edge JDK die diezelfde middag op dezelfde host andere Java-tools volledig liet vastlopen. De catalogusclaim wilde ik echter niet testen; de toetsbare vraag is kleiner. Wat doet Tika eigenlijk als de invoer tegen je liegt? Daarom bouwde ik een gecontroleerde set fixtures waarbij elk contentblok een uniek marker-token bevat, renderde ik hetzelfde logische document naar negen dragers, en viel ik het geheel aan met verkeerde extensies, ontbrekende extensies, helemaal geen bestandsnamen, nulexbestanden en half weggeschreven binaries.

Detectie is waar het interessante gedrag zit. Ik hernoemde een PDF naar .txt en vroeg Tika wat het was; het antwoord was application/pdf. Daarna verwijderde ik de bestandsnaam helemaal, pipe’de ik de ruwe bytes via stdin binnen, en kreeg ik hetzelfde antwoord. Voor de vijf content-detecteerbare formaten in mijn set gold dat in alle 20 unieke logische condities: drie bestandsnaamcondities plus per formaat één conditie zonder bestandsnaam. De testharness draaide de stream-variant drie keer onder verschillende labels, goed voor 30 geslaagde ruwe runs, maar die herhalingen leveren geen onafhankelijke bewijsvoering op. PDF en RTF bevatten herkenbare bytes; DOCX verraadt zijn container; HTML en XML zijn te herkennen aan markup of root content. Verschillende mechanismen, hetzelfde nuttige resultaat in deze fixture-set: de extensie won niet van de content. En dan is er nog het regime van de tekstfamilie, waar Markdown meteen naar text/plain terugvalt zodra de bestandsnaam fout is of ontbreekt. In dit geval hing de identiteit volledig aan .md.

Twee grenzen bij elk cijfer dat volgt. Ik testte Apache Tika 3.3.2 — gecontroleerd op 27 juli 2026, destijds nog steeds de nieuwste stabiele release; de 4.0.0-lijn bestaat op Maven Central alleen als alpha- en beta-builds. Het project stond bij mijn controle op 27 juli 2026 op ongeveer 3,9k GitHub-stars en heeft een Apache-2.0-licentie, zo vrij commercieel als licenties maar kunnen zijn. En ik heb OCR helemaal niet getest. Geen enkele gescande pagina, geen enkele PDF die alleen uit afbeeldingen bestond. Tesseract en poppler zijn niet geïnstalleerd op de machine waarop ik dit draaide, dus elke OCR-route was al geblokkeerd voordat die begon. Er zijn hier geen OCR-cijfers, omdat er simpelweg geen OCR-cijfers zijn.

Wat Tika is, zodra je stopt met de marketing op de doos te lezen

De gangbare aanname is dat Apache Tika een documentconverter is — stop er een DOCX in en je krijgt netjes opgemaakte Markdown terug, met koppen en tabellen intact. Dat is het niet, en hoe sneller dat duidelijk is, hoe beter de tool eruitziet.

De hier geteste route heeft drie relevante stappen: een content-type detector, een dispatcher die de bytes naar de juiste parser doorgeeft, en de --text-output van de CLI, die platte tekst uitspuugt naast apart beschikbare metadata. In dat outputcontract zijn er geen Title-objecten, geen ListItem en geen gereconstrueerd tabelraster. Tika biedt ook andere handlers en API’s, waaronder XHTML-/SAX-georiënteerde output; die heb ik niet getest. Elke conclusie over structuur hieronder gaat dus over tika-app --text, niet over de bewering dat de toolkit nergens een gestructureerde eventstream zou hebben.

Dat klinkt als een beperking, en op één vlak is het dat ook. Maar het betekent ook dat Tika niets verkeerd hoeft te classificeren, en juist dat is de ruil die minder nette alternatieven in de andere richting maken.

Detectie zelf verloopt in een gedocumenteerde volgorde: eerst signature-bytes, dan inspectie van de XML-root, daarna de filename-glob, en pas daarna eventueel een type dat je zelf hebt meegegeven (de detectiedocumentatie van Tika zet dit uiteen). Pas zodra het type is vastgesteld, geeft de dispatcher de bytes door aan de passende meegebundelde parser — PDFBox, POI, jsoup, TextAndCSVParser voor de tekstfamilie.

Dat onderscheid tussen detecteren en parsen is niet zomaar interne trivia. Het is waarom een bestand dat te kapot is om te parsen toch correct getypeerd kan worden, en dat is meteen de meest praktische truc die Tika biedt zodra dingen beginnen te breken.

Setup: één jar, één commando, en een JVM die niet kieskeurig is

Installatie betekent downloaden. tika-app-3.3.2.jar van Maven Central is ongeveer 67 MB — een fat jar met elke parser erin — en daarna is het gewoon java -jar tika-app-3.3.2.jar --text file.pdf. Geen configuratiebestand, geen modelgewichten, geen post-installstap, geen brew install-keten om doorheen te lopen.

Het JDK-verhaal verraste me. Ik draaide het geheel op OpenJDK 26.0.1, een niet-LTS build op het scherp van de snede, en --version, --text, --metadata en --detect keerden allemaal terug met exit 0 zonder compatibiliteitsklachten. Dat verdient het om te benoemen, want ik zette op dezelfde host, in dezelfde sessie, ook Apache Nutch onder druk en die crawlcyclus weigerde volledig op JDK 26 te draaien — die heeft een LTS op 21 of lager nodig, mede door het verdwijnen van SecurityManager in nieuwere JDK’s. Tika maakte het niets uit. Als je Java-tools al vermijdt vanwege precies dat soort pijn, dan is Tika niet waar je eraan onderdoor gaat.

Twee eerlijke kanttekeningen bij de setup. De CLI start per oproep een verse JVM, dus koude start is echt een factor — 131 invocaties voor mijn harness duurden ongeveer een minuut, vooral JVM-opwarmtijd. Als je bestanden op volume verwerkt, wil je de library- of servermodus, niet een shell-loop over de jar. En het verhaal van ‘geen dependencies nodig’ heeft een harde grens: extractie van de tekstlaag van PDF’s heeft niets externs nodig, maar OCR heeft tesseract en poppler nodig. PDF’s met een tekstlaag, DOCX, ODT, RTF, HTML, XML, TXT, Markdown en CSV parseerden allemaal op een host zonder die tools. Gescande documenten zouden dat niet hebben gedaan, en ik heb niet gedaan alsof wel.

Dat contrast wordt nog scherper naast de zustertool die ik diezelfde dag testte, unstructured, waarvan de route voor elektronische PDF’s volledig geblokkeerd was omdat het importeren van de PDF-module de inferentiestack (torch en aanverwanten) al tijdens het laden meeneemt — dus vóór strategy dispatch, waardoor zelfs de ‘fast’ strategy niet kan importeren zonder die stack. Tika parseerde de tekstlaag van dezelfde PDF met een gewone java -jar.

De leugende-extensietest: MIME-type-detectie die negeert hoe je het bestand noemt

Measured results chart: Type detection across filename conditions

Acht formaten, elk aangeboden met een juiste extensie, een bewust verkeerde extensie, of helemaal geen extensie, plus een byte stream zonder bestandsnaam op stdin. Dat zijn 32 unieke logische condities. De oorspronkelijke harness draaide ook de identieke stream-bytes nog eens onder elk bestandsnaamlabel, goed voor 48 ruwe executies; die drie stream-rijen vallen samen tot één conditie, omdat stdin geen bestandsnaam bevat.

FixtureEcht typeHernoemd naarJuiste extLeugenextGeen extRuwe stream, geen bestandsnaam
PDFapplication/pdf.txt
DOCXOOXML wordprocessingml.jpg
RTFapplication/rtf.html
HTMLtext/html.csv
XMLapplication/xml.txt
Platte teksttext/plain.pdf
Markdowntext/markdown.pdftext/plaintext/plaintext/plain
CSVtext/csv.txttext/plaintext/plaintext/plain

(De streamkolom bundelt alle drie de extensiecondities samen, want zonder bestandsnaam valt er voor de glob niets te lezen.)

De vijf content-detecteerbare formaten — PDF, DOCX, RTF, HTML en XML — kwamen in 20 van 20 unieke condities op hun echte type uit (en in 30 van 30 ruwe harness-runs, inclusief gedupliceerde stream-runs). Een PDF die report.txt heet, bleef een PDF. Een DOCX die photo.jpg heet, bleef een DOCX. Geen van beide had een bestandsnaam nodig. Dat betekent niet dat al die vijf formaten vaste bytesignatures gebruiken: PDF en RTF hebben herkenbare headers, DOCX is een op ZIP gebaseerd containerformaat, en HTML/XML worden herkend via markup of root content. In deze fixtures won de leugende extensie niet.

Daarna het regime van de tekstfamilie. Markdown werd alleen text/markdown wanneer de .md-extensie aanwezig en leesbaar was. Hernoem het, verwijder de extensie of stuur het als stream, en in deze test zakte het terug naar text/plain. CSV gedroeg zich op dit bewust kleine raster hetzelfde: text/csv kwam alleen via de .csv-glob binnen. Geteld over unieke condities werd Markdown en CSV elk in één van de vier condities als hun specifieke type herkend; platte tekst was al text/plain, dus daar was niets om van te ‘collapsen’. De ruwe 48-run harness blijft nuttig als bewijs van herhaalbaarheid, maar niet als grotere noemer.

Eén detail is hier in Tika’s voordeel: de leugende extensie wint ook niet. Mijn naar .pdf hernoemde Markdown-fixture kwam terug als text/plain, niet als application/pdf. Tika geloofde de leugen niet; het kon alleen de waarheid niet bevestigen. Terugvallen naar het oudertype is een veel betere fout dan zelfverzekerd iets verkeerds te beweren, en dat text/markdown een gedocumenteerd subtype van text/plain is, maakt die fallback principieel in plaats van willekeurig.

Er is wel een kanttekening specifiek voor CSV. Tika heeft een statistische CSV-detector, en tijdens het parsen — bevestigd doordat TextAndCSVParser opdook in de X-TIKA:Parsed-By-keten — werd mijn kleine raster van 2 kolommen bij 3 rijen als text/plain in plaats van text/csv herkend. Dat is één observatie op een bewust minimale fixture. Een grotere of geciteerde CSV kan de detector prima triggeren. Ik beweer niet dat CSV-contentdetectie stuk is; ik beweer dat op dit raster de extensie is wat text/csv opleverde.

Waarom dit belangrijk is in een echte uploadpipeline

Het concrete scenario is een uploadrouter. Stel dat je gebruikersuploads accepteert en ze op type doorstuurt: PDF’s naar de invoice-parser, spreadsheets naar de ledger-importer, de rest naar een tekstindex. Als je de extensie vertrouwt, belandt iemand die een PDF uploadt met de naam notes.txt in de verkeerde tak — en dat is nog de onschuldige variant; de kwaadaardige versie is een polyglot-bestand met een vriendelijke extensie.

Voor de binaire en markup-fixtures die ik hier testte, routeerde Tika op content, ook nadat de bestandsnaam verdwenen was. Dat is nuttig wanneer een blobstore of HTTP-bodyhandler die naam al heeft weggegooid. Dit resultaat dekt echter niet Tika’s lange staart, dubbelzinnige bestanden of polyglots af. De geteste tekstfamilie-fixtures gedroegen zich anders: toen de pipeline de bestandsnamen verwijderde, kwamen Markdown en CSV als text/plain binnen, waardoor regels die op hun specifieke mediatypes mikken stopten met afgaan. Bewaar de originele bestandsnaam als sidecar-metadata in plaats van te verwachten dat contentdetectie die weer kan reconstrueren.

De ingebedde content bleef overeind. --text maakte de structuur plat.

Fidelity is de tweede as, en die splitst netjes in tweeën. Ik renderde één canoniek document (koppen, twee alinea’s bodytekst, een bulletlijst, een genummerde lijst en een slotalinea) naar HTML, Markdown, platte tekst, DOCX, PDF, RTF, ODT en XML, plus een tabeldocument naar HTML, Markdown, tekst, DOCX, CSV en XML. Veertien drager-renderings. Elk blok bevat een uniek token — zztitle1, zzitem3, zztblcell_beta enzovoort — zodat ‘blijft bestaan’ versus ‘verdwijnt’ een exacte substring-check is, geen interpretatie.

Recall van marker-tokens kwam op 1.000 uit voor alle veertien renderings. Geen enkel ingebed token ging verloren: elke getagde tabelcel, elk lijstitem en elke kop was aanwezig. Drie lokale herhalingen per drager na warmup gaven byte-identieke --text-output terug. Dit oracle zegt niets over niet-getagde karakters, volgorde, whitespace, Unicode-normalisatie, herhaalde content, links, headers, voetnoten of ingebedde objecten. Het is een check op aanwezigheid van blokken, geen bewijs van volledige documentfidelity.

De platte tekstuitvoer geeft het grootste deel van de bronstructuur op.

Dit is het HTML-tabeldocument zoals het uit --text komt:

	Tool	Throughput

	zztblcell_alpha	120

	zztblcell_beta	95

Met tabs samengevoegde regels. De headerregel is niet als header gemarkeerd. Er is geen raster, geen celgrenzen behalve een tab, geen manier om te weten dat dit ooit een <table> was. De DOCX-tabel vlakt op precies dezelfde manier af.

Lijsten zijn subtieler, en daar splitst het zich op basis van wat de bron daadwerkelijk bevatte:

Wat de bullet in de bron wasDragersWat --text teruggeeft
Een letterlijk teken — deze renderings schreven - als echte tekst wegplatte tekst, Markdown, RTF, ODT, PDFde - blijft behouden, omdat Tika gewoon tekens doorgeeft
Echte structuur — een HTML <li>, een DOCX-stijl List BulletHTML, DOCXde marker verdwijnt volledig en je krijgt alleen de itemtekst: in HTML tab-ingesprongen, in DOCX een kale regel zonder opmaak

Tika zet nooit een marker opnieuw om in iets dat het niet als tekst kreeg. Zelfde inhoud, ander uitziende output.

Het Markdown-geval maakt het punt helder. Geef Tika een .md-bestand met een pipe-table en de pipes komen letterlijk terug, wat lijkt op behoud van structuur. Dat is het niet. Tika parseerde het als tekst en gaf de bytes terug. Niemand begreep die tabel.

De gemeten afspraak is dus kleiner: alle geplante markers bleven behouden, terwijl --text geen getypeerde elementen of een reconstrueerbaar tabelraster behield. Dat een parserfout noemen zou de kern missen. Platte extractie ontwijkt bewust het probleem van elementclassificatie; daardoor kan het ook niet voldoen aan een downstream consumer die juist die elementtypes nodig heeft. Als je getypeerde blokken of gereconstrueerde tabellen nodig hebt, is --text één onderdeel van de stack, niet de stack. Andere Tika-handlers kunnen meer structuur blootleggen, maar die vielen buiten deze run.

De standaardkanttekening bij alle fidelity-cijfers hier: ze komen uit gecontroleerde synthetische fixtures op één machine, één versie, één JDK. Ze laten zien dat de getagde blokken in de output aanwezig waren. Ze bewijzen geen teken-voor-teken behoud of nauwkeurigheid op een rommelige echte corpus.

Metadata: genormaliseerd en verfrissend onwillig om iets te verzinnen

Measured results chart: Metadata recovery by carrier

Ik heb bekende author-, title- en creation-datewaarden in elke drager met een metadata-laag ingebed en vervolgens gekeken wat terugkwam.

Dragerauthor → dc:creatortitle → dc:titlecreated → dcterms:created
HTML (<meta name=author>, <title>)niet ingebed
DOCX (core properties)✅ exact 2021-03-15T09:30:00Z
PDF (info-dict)aanwezig, maar het was de eigen timestamp van de generator — niet meegeteld
ODT (meta.xml)✅ exact 2021-03-15T09:30:00Z
TXT / MD / CSV / RTF / XMLgeen metadata-laag

Author en title werden teruggevonden op 4 van 4 metadata-dragende formaten, en — dat is het mooie eraan — ze zijn genormaliseerd. Een HTML <meta name="author">, een DOCX core property, een PDF /Author-entry en een ODT dc:creator-element komen allemaal binnen onder dezelfde dc:creator-key. Je schrijft één consumer, geen vier.

created is de eerlijke hobbel. DOCX en ODT gaven mijn exact ingebedde 2021-timestamp terug. De PDF gaf een creation date terug, maar dat was de datum die de generatorbibliotheek tijdens het bouwen heeft gezet, niet de waarde die ik wilde inbedden — dus ik scoor die als aanwezig, niet als hersteld. En de formaten zonder metadata-laag gaven helemaal niets terug, wat precies het juiste antwoord is. Tika verzint geen author uit de tekstbody.

Het expres kapot maken, en de triagetruc die daaruit voortkomt

Vier vijandige invoeren. Een bestand van nul bytes. Een geldige PDF-header met de body afgekapt. Een afgekorte DOCX-ZIP. En een UTF-8-bestand met multibyte-karakters zonder BOM en zonder encoding-declaratie. Dit zijn lokale fixturevormen, geen Tika-drempels.

De onderliggende harness, gegenereerde fixtures, ruwe JSON, jar-checksum en omgevingsmanifest zijn niet aan deze draft gekoppeld. Een externe lezer kan de exacte noemers daarom nog niet onafhankelijk reproduceren. Behandel de tabellen als gerapporteerde observaties; publicatie moet een stabiele bundle toevoegen voordat deze cijfers als extern bewijs worden gebruikt.

Input--text / --jsonWat het gooide--detect
0-byte bestandexit 1, lege stdoutZeroByteFileException: InputStream must have > 0 bytesexit 0 → text/plain met bestandsnaam, application/octet-stream van stream
Afgekorte PDFexit 1, lege stdoutTikaException: TIKA-198: Illegal IOException from PDFParserexit 0 → application/pdf
Afgekorte DOCXexit 1, lege stdoutPOI FATAL: "XML document structures must start and end within the same entity"exit 0 → OOXML-type
UTF-8, geen BOM, geen declaratieexit 0nietsexit 0 → text/plain, charset UTF-8

Extractie faalt luidruchtig, en deze fouten hebben allemaal dezelfde buitenvorm. Het 0-byte-bestand, de afgekorte PDF en de afgekorte DOCX produceerden elk een exception, exit 1 en lege stdout. De CLI slikt de fout dus niet weg in een keurig lege uitkomst. Procesveilig in deze gevallen — geen hang, geen segfault — maar de aanroeper moet exitstatus en stderr controleren in plaats van alleen naar een lege string te kijken.

Detectie staat los van parsen. Bij beide afgekorte binaries gaf --detect exit 0 terug met het verwachte type op basis van de intacte begincontent; daarna faalde de parser op de kapotte body. Een pipeline kan detectie dus als apart triagesignaal gebruiken vóór of na een mislukte parse. Of detect-first de beste standaard is, hangt af van de deploymentmodus: deze test benchmarkt detect-first niet tegen alleen parse, en twee verse CLI-JVM’s zijn op volume misschien de verkeerde ruil.

Charset-detectie werkt. Het UTF-8-bestand zonder BOM en zonder declaratie werd als UTF-8 gedecodeerd en 日本語テスト kwam intact door. Kleine kanttekening voor iedereen die de metadata-dicts leest: mijn puur ASCII-fixtures rapporteren charset=ISO-8859-1, wat op ASCII-bytes niet van UTF-8 te onderscheiden is. Dat is geen misser, dat is een gelijkspel.

Tika naast unstructured: dezelfde bestandstypen, ander doel

Beide tools zijn in dezelfde onderzoeksessie gebruikt, maar dit is een taxonomie van outputcontracten, geen symmetrische benchmark. De tools zijn op verschillende uitkomsten beoordeeld.

Gerelateerde review: Unstructured-review.

Apache Tikaunstructured
Waar ik het op matcontentfidelity: ging er iets verloren?elementclassificatiefidelity: kreeg elk blok het juiste type?
Resultaatalle geplante markers aanwezig in veertien renderingsin de aparte classificatietest had een plain-text tabel een Table-recall van 0.000, en één kop met een werkwoord werd als narrative text geclassificeerd
Teruggestuurde getypeerde elementengeen — er kwam ook geen structuur terugTitle, NarrativeText, ListItem, Table — precies wat Tika weigert te doen
OCRgeblokkeerd op mijn host, tesseract ontbreektgeblokkeerd op mijn host, tesseract ontbreekt

Platte output die markers behoudt versus getypeerde elementen met waargenomen classificatiefouten. Kies wat je downstream consumer nodig heeft. Als het een zoekindex of een LLM-contextvenster is, kan platte tekst genoeg zijn. Als het op elementtype leunt, kan Tika’s --text-route dat contract niet leveren.

Geen van ons heeft cijfers voor gescande documenten.

Plus- en minpunten

Pluspunten

  • Content-type detectie negeerde misleidende bestandsnamen in 20/20 unieke condities voor de vijf content-detecteerbare fixtures; gedupliceerde stream-runs kwamen hetzelfde uit.
  • Alle geplante markers bleven behouden in alle 14 drager-renderings, inclusief de getagde tabelcellen en lijstitems.
  • Herhaalbaar in drie lokale reruns: elke drager gaf binnen deze omgeving byte-identieke tekst terug.
  • Metadata werd over formaten heen genormaliseerd — dc:creator / dc:title / dcterms:created ongeacht het bronformaat, teruggevonden op 4/4 metadata-dragende formaten.
  • Echt dependencyvrij voor de formaten die ik testte: tekstlaag-PDF, DOCX, ODT, RTF, HTML parseren allemaal uit één jar zonder externe binaries.
  • Draait probleemloos op OpenJDK 26 — geen beperking tot LTS.
  • Detectie blijft correct (exit 0) op afgekorte binaries, wat een betrouwbaar triagesignaal geeft wanneer parsen faalt.
  • Apache-2.0, volwassen, actief onderhouden.

Minpunten

  • Markdown- en CSV-identiteit hangt volledig af van de bestandsnaam; 10 van de 18 signatureloze cellen vielen terug naar text/plain zodra de bestandsnaam ontbrak of fout was.
  • --text geeft geen elementtypes terug; tabelrasters vlakken af naar regels met tabs en structurele lijstmarkers verdwijnen.
  • Extractie gooit ongevangen exceptions op lege en corrupte inputs; beide gevallen zien er vanuit de extractie-aanroep zelf identiek uit.
  • 67 MB jar plus een per-invocation JVM-koude start in CLI-modus.
  • OCR en gescande afbeeldings-PDF’s zijn hier volledig niet getest — tesseract en poppler ontbraken, dus over dat pad wordt geen enkele claim gedaan.
  • Elk cijfer hier is synthetische ground truth op één machine, één versie. Nauwkeurigheid op echte corpora, versleutelde bestanden, embedded/recursieve documenten en throughput op schaal zijn niet gemeten.

Voor wie het wel en niet geschikt is

Tika past wanneer je input bestanden zijn die je al hebt en je output tekst plus metadata moet zijn die een machine kan indexeren. Zoekindexing, e-discovery, archiefverwerking, een corpus voeden aan een LLM, de content-type-validatielaag van een uploadpipeline bouwen. Het is nuttig als eerste triage- en normalisatiestap vóór iets slimmers: detecteer de geteste types, extraheer platte tekst en geef het door met expliciete checks op content die je pipeline zich niet kan permitteren te verliezen.

Sla het over — of liever: stop niet bij --text — als je getypeerde elementen, gereconstrueerde tabellen of documentlayout nodig hebt. Sla het ook over als je documenten scans zijn, althans totdat je tesseract hebt geïnstalleerd en je eigen cijfers hebt gedraaid, want ik heb er geen. Voor volumewerk moet je de library- of servermodus benchmarken tegen de CLI op representatieve documenten. Procesopstart was zichtbaar in deze small-file harness, maar throughput en resourcekosten zijn niet gemeten.

De valkuil die mensen vaak raakt: als je opslaglaag bestandsnamen wegstript en je werkt met Markdown of CSV, vertrouw Tika dan niet om die van platte tekst te onderscheiden. Bewaar de oorspronkelijke naam.

Alternatieven, en waar Thunderbit past

Eerst de eerlijke afbakening, want de juiste vergelijking hier gaat over inputs, niet over kwaliteit. Tika is een gratis, Apache-2.0, self-hosted toolkit voor het parsen van bestanden. Bestanden die je al op disk of in een bucket hebt. Het haalt geen pagina’s op, draait geen JavaScript, worstelt niet met anti-bot en doet ook niet alsof.

Dat is precies de grens waar een beheerde web-extractieservice, waaronder onze eigen Thunderbit, in de architectuur kan verschijnen: die haalt live pagina’s op, terwijl Tika bestanden parseert die al in jouw bezit zijn. Dit artikel heeft die diensten niet tegen Tika gebenchmarkt, en ze zijn ook geen vervangers voor dezelfde invoer.

De nette scheiding: Tika voor documenten die je al hebt, een beheerde extraction API voor webpagina’s die je nog moet ophalen. Veel pipelines draaien beide — crawlen en extracten aan de webkant, Tika op de PDF- en DOCX-bijlagen die terugkomen.

Als je vergelijkt met het bredere open-sourceveld, heb ik ook de volledige vergelijking van open-source scrapers uitgewerkt, een overzicht van de nuttigste scraping-projecten op GitHub, een praktische Crawl4AI-review over de browser-gedreven Markdown-aanpak, en een bredere round-up van scraping tools. Voor de no-code route is er ook een walkthrough over hoe je een site met AI scrapt.

Probeer Thunderbit voor webdata-extractie

Oordeel

Moet je Apache Tika gebruiken? Ja, als je taak is om heterogene bestanden om te zetten in platte tekst en genormaliseerde metadata, en je de velden of markers valideert die je eigen pipeline zich niet kan permitteren te verliezen.

De detector was het sterkste onderdeel van deze run. Die gaf het verwachte type in 20 van 20 unieke condities voor de vijf content-detecteerbare fixtures, inclusief streams zonder bestandsnaam. Alle geplante markers bleven behouden over veertien renderings, en de output herhaalde byte-voor-byte in drie lokale reruns. Nuttig bewijs. Nog steeds synthetisch bewijs. Dat dit uit één jar op deze JDK draaide, zonder externe binaries voor de niet-OCR-paden die getest zijn, hield de deployment aangenaam saai.

Wel moet je het goed inschatten. Elke tabel die je het voert komt terug als regels met tabs ertussen. Elke structurele lijstmarker verdwijnt. Markdown en CSV verliezen hun identiteit zodra de bestandsnaam wegvalt. Lege bestanden en corrupte bestanden gooien dezelfde foutvorm, en je hebt de aparte detect-aanroep nodig om ze uit elkaar te houden. En over OCR, de vraag waar veel Tika-gebruikers het meest om geven, heb ik niets te bieden: ik kon het niet draaien en ga er ook niets over schatten.

Binnen die grenzen doet Tika een weinig glamoureuze maar opmerkelijk betrouwbare klus. Het leest de bytes, niet het label op de doos. Vraag het alleen niet in welke vorm die bytes kwamen.

Probeer Thunderbit voor webdata-extractie Get Started Free

Veelgestelde vragen

Detecteert Apache Tika bestandstypen correct als de extensie fout is? Voor de vijf hier geteste content-detecteerbare fixtures: ja. PDF, DOCX, RTF, HTML en XML kwamen in alle 20 unieke logische condities (30 ruwe runs met gedupliceerde stream-executies) uit op hun verwachte mediatype, inclusief misleidende extensies, geen extensie en streams zonder bestandsnaam. Een PDF met de naam .txt werd nog steeds application/pdf. Markdown en de kleine CSV-fixture waren afhankelijk van bestandsnaaminformatie en vielen terug naar text/plain wanneer die ontbrak of fout was.

Behoudt Tika tabellen en documentstructuur? Niet in de hier geteste --text-modus. Tabelrasters kwamen terug als regels met tabs ertussen, zonder cel- of headersemantiek, en structurele lijstmarkers (een HTML <li>, een DOCX List Bullet-stijl) verdwenen. Alle geplante markers bleven behouden in alle 14 drager-renderings, maar dat bewijst geen volledige contentfidelity, en --text levert geen elementtyping. Voor getypeerde elementen of gereconstrueerde tabellen moet je een andere Tika-outputhandler testen of een andere tool erbij gebruiken.

Kan Apache Tika OCR doen op gescande PDF’s? Tika ondersteunt OCR via Tesseract, maar ik heb het niet getest, en niets in deze resultaten is een claim daarover. Tesseract en poppler ontbraken op mijn testhost, dus elk OCR- en scanned-image-pad was al geblokkeerd voordat het draaide. Er zijn nergens OCR-cijfers in deze test. Als OCR jouw use case is, installeer tesseract en benchmark het zelf — beschouw dat deel van Tika hier als onbevestigd.

Wat doet Tika met lege of corrupte bestanden? Het faalt luidruchtig in plaats van stilletjes. Een bestand van 0 bytes gooit ZeroByteFileException; een afgekorte PDF gooit een TikaException vanuit PDFParser; een afgekorte DOCX gooit een POI XML-fout. Alle drie eindigen met exit 1 en lege stdout, dus leeg en corrupt zijn vanuit alleen de extractie-aanroep niet van elkaar te onderscheiden. Detectie blijft echter robuust — --detect gaf op beide afgekorte binaries exit 0 terug met het juiste type, wat het een betrouwbare triagestap maakt vóór je tijd aan een parse besteedt.

Wat dekte de Tika-test niet af? Vier dingen, expliciet. OCR en gescande beelden (geblokkeerd, niet getest). Nauwkeurigheid op echte corpora — alle resultaten zijn gecontroleerde synthetische fixtures met geplante marker-tokens, wat fidelity meet tegen bekende labels in plaats van nauwkeurigheid op rommelige echte documenten. Resourcekosten, throughput en piekgeheugen, die ik niet heb gemeten. En de lange staart van de claim ‘duizend bestandstypen’: ik testte negen representatieve, dependencyvrije formaten, niet de volledige catalogus. Alles hier is Tika 3.3.2 op OpenJDK 26.0.1, macOS arm64, één machine.

Ke
Ke
CTO bij Thunderbit | Senior Data Scientist & ML-expert Met bijna tien jaar ervaring in machine learning en data science is Ke Shen alumnus van Columbia University en voormalig Senior Data Scientist bij Walmart Labs. Met diepgaande, door vakgenoten erkende expertise in Python, R, Java en statistiek deelt hij praktijkgerichte inzichten over hoe je complexe AI-algoritmen van theorie naar productieklare architectuur brengt.
Topics
Web Scraping ToolsAI Web Scraper
Inhoudsopgave
Thunderbit · AI-webdata-agent

Gegevens extraheren van elke pagina in 1 klik

Vertrouwd door meer dan 250.000 gebruikers
gratis abonnement beschikbaar
Van webpagina naar spreadsheet
Beschrijf wat je nodig hebt — Thunderbit's AI Agent scrapt het en exporteert het naar Excel, Google Sheets, Airtable of Notion. Gratis om te starten.
Chrome Store Rating
PRODUCT HUNT#1 Product of the Week