Apache Tika is de documentparsing-toolkit van de Apache Software Foundation: geef het een bestand van vrijwel elk type en je krijgt platte tekst terug, plus een genormaliseerde metadata-dictionary. In de project-README wordt ondersteuning voor meer dan duizend bestandstypen genoemd, en Tika bereikt dat doordat het zelf alle specialistische bibliotheken meelevert — PDFBox voor PDF's, Apache POI voor Office-documenten, jsoup voor HTML, een ODF-lezer voor ODT — zodat alles als één grote jar wordt geleverd, zonder dat er tijdens het parsen nog iets hoeft te worden opgehaald. In een datapijplijn is het de onopvallende eerste stap: het onderdeel vóór een zoekindex, een e-discovery-reviewset of een LLM-corpus dat een bonte stapel bestanden omzet in iets eenduidigs. Eigenlijk zijn het twee taken: uitzoeken wat een byte stream is, en daarna de tekst en metadata eruit 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 stap na installatie, en het draaide probleemloos op een bleeding-edge JDK die andere Java-tools op dezelfde host diezelfde middag volledig stillegde. Maar die catalogusclaim wilde ik eigenlijk niet testen; de echte vraag is smaller. Wat doet Tika als de input liegt? Daarom maakte ik een gecontroleerde set testbestanden waarin elk contentblok een unieke marker-token heeft, rendeerde ik hetzelfde logische document naar negen containerformaten, en viel ik alles aan met verkeerde extensies, ontbrekende extensies, helemaal geen bestandsnamen, lege bestanden en halfgeschreven 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 volledig, stuurde de ruwe bytes via stdin, en kreeg hetzelfde antwoord. Over de vijf content-detecteerbare formaten in mijn set gebeurde dat in alle 20 unieke logische voorwaarden: drie bestandsnaamcondities plus één bestandsnaamloze streamconditie per formaat. De testharness voerde de stream-case drie keer uit onder verschillende labels en leverde daarmee 30 succesvolle ruwe runs op, maar die herhalingen tellen niet als onafhankelijk bewijs. PDF en RTF hebben herkenbare bytes; DOCX heeft zijn container; HTML en XML zijn te identificeren op basis van markup of root-content. Verschillende mechanismen, hetzelfde bruikbare resultaat in deze testset: de extensie won het niet van de inhoud. En dan is er nog de tekstfamilie, waar Markdown meteen naar text/plain terugvalt zodra de bestandsnaam fout of verdwenen is. Daar hing de identiteit hier volledig aan .md.
Twee grenzen bij alles wat volgt. Ik heb Apache Tika 3.3.2 getest — op 27 juli 2026 gecontroleerd en toen was dit nog de nieuwste stabiele release; de 4.0.0-lijn bestaat alleen als alpha- en beta-build op Maven Central. Het project had op 27 juli 2026 ongeveer 3,9k GitHub-stars, en is Apache-2.0 gelicentieerd, wat zo ongeveer neerkomt op de meest commercieel ontspannen licentie die je kunt hebben. En ik heb OCR helemaal niet getest. Geen enkele gescande pagina, geen enkele image-only PDF. Tesseract en poppler stonden niet op de machine waarop ik dit draaide, dus alle OCR-routes waren al geblokkeerd voordat ze begonnen. Er staan hier geen OCR-cijfers, omdat er gewoon geen OCR-cijfers zijn.
Wat Tika is, zodra je stopt met de marketing op de doos
De gangbare aanname is dat Apache Tika een documentconverter is — stop er een DOCX in en krijg netjes Markdown terug, met koppen en tabellen intact. Dat is het niet, en hoe sneller dat duidelijk is, hoe beter de tool eruitziet.
Het pad dat hier getest is, heeft drie relevante stappen: een content-type detector, een dispatcher die de bytes naar de juiste parser stuurt, en de --text-output van de CLI, die platte tekst uitspuugt samen met apart beschikbare metadata. In dat outputcontract zitten 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 heeft.
Dat klinkt als een beperking, en in één opzicht is dat ook zo. Maar het betekent ook dat Tika niets verkeerd hoeft te classificeren, en precies dát is de afweging die zijn minder nette tegenhangers aan de andere kant maken.
Detectie zelf verloopt volgens een gedocumenteerde volgorde: eerst signature-bytes, daarna XML-rootinspectie, daarna de filename-glob, en ten slotte elk type dat je zelf hebt meegegeven (de eigen detectiedocumentatie van Tika zet dit uiteen). Pas zodra het type is vastgesteld, geeft de dispatcher de bytes door aan de bijbehorende ingebouwde parser — PDFBox, POI, jsoup, TextAndCSVParser voor de tekstfamilie.
Die scheiding tussen detectie en parsing is geen intern weetje. Het is waarom een bestand dat te kapot is om te parsen tóch correct getypeerd kan worden, en dat blijkt uiteindelijk de meest praktische truc te zijn die Tika biedt zodra dingen beginnen te breken.
Setup: één jar, één commando en een JVM die niet kieskeurig doet
Installeren is 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 stap na installatie, geen brew install-keten om doorheen te lopen.
Het JDK-verhaal verraste me. Ik draaide alles op OpenJDK 26.0.1, een bleeding-edge non-LTS build, en --version, --text, --metadata en --detect gaven allemaal exit 0 terug zonder compatibiliteitsklachten. Dat noem ik expliciet, omdat ik op dezelfde host in dezelfde sessie Apache Nutch testte en de crawlcyclus daar helemaal niet wilde draaien op JDK 26 — daarvoor is een LTS van 21 of lager nodig, dankzij het verwijderen van de SecurityManager in nieuwere JDK's. Tika maakte het niets uit. Als je JVM-tools hebt vermeden vanwege precies dat soort ellende, dan is Tika niet de plek waar het pijn doet.
Twee eerlijke kanttekeningen bij de setup. De CLI start per run een nieuwe JVM, dus koude start is reëel — 131 invocations voor mijn harness kostten ongeveer een minuut, grotendeels JVM-warming-up. Als je bestanden op volume verwerkt, wil je de library- of servermodus, niet een shell-loop over de jar. En het dependency-vrije verhaal heeft een harde grens: extractie van de tekstlaag in 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 parsten allemaal op een host waar geen van beide geïnstalleerd was. Gescande documenten zouden dat niet hebben gedaan, en ik heb niet gedaan alsof.
Dat contrast is scherper naast de zustergibliotheek die ik dezelfde dag testte, unstructured, waarvan het pad voor elektronische PDF's volledig werd geblokkeerd omdat het importeren van de PDF-module de inferentiestack (torch en vrienden) al laadt — nog vóór strategy dispatch, dus zelfs de "fast"-strategie importeert niet zonder. Tika pakte de tekstlaag van dezelfde PDF gewoon met een kale java -jar.
De test met de liegende extensie: mime-type-detectie die negeert hoe je het bestand noemde

Acht formaten, elk aangeboden met een correcte extensie, een expres verkeerde extensie of geen extensie, plus een bestandsnaamloze byte stream op stdin. Dat zijn 32 unieke logische voorwaarden. De oorspronkelijke harness draaide dezelfde stream-bytes ook nog eens één keer onder elk bestandsnaamlabiel, goed voor 48 ruwe uitvoeringen; die drie stream-rijen vallen samen tot één conditie omdat stdin geen bestandsnaam bevat.
| Fixture | Werkelijk type | Hernoemd naar | Correcte ext | Liegende ext | Geen ext | Ruwe stream, zonder bestandsnaam |
|---|---|---|---|---|---|---|
application/pdf | .txt | ✅ | ✅ | ✅ | ✅ | |
| DOCX | OOXML wordprocessingml | .jpg | ✅ | ✅ | ✅ | ✅ |
| RTF | application/rtf | .html | ✅ | ✅ | ✅ | ✅ |
| HTML | text/html | .csv | ✅ | ✅ | ✅ | ✅ |
| XML | application/xml | .txt | ✅ | ✅ | ✅ | ✅ |
| Platte tekst | text/plain | .pdf | ✅ | ✅ | ✅ | ✅ |
| Markdown | text/markdown | .pdf | ✅ | ❌ text/plain | ❌ text/plain | ❌ text/plain |
| CSV | text/csv | .txt | ✅ | ❌ text/plain | ❌ text/plain | ❌ text/plain |
(De stream-kolom bundelt alle drie extensiecondities, want zonder bestandsnaam is er niets voor de glob om te lezen.)
De vijf content-detecteerbare formaten — PDF, DOCX, RTF, HTML en XML — kwamen in 20 van 20 unieke voorwaarden op het juiste type uit (en 30 van 30 ruwe harness-uitvoeringen, inclusief dubbele stream-runs). Een PDF met de naam report.txt bleef een PDF. Een DOCX met de naam photo.jpg bleef een DOCX. Geen van beide had een bestandsnaam nodig. Dat betekent niet dat al deze vijf vaste byte signatures gebruiken: PDF en RTF hebben herkenbare headers, DOCX is een ZIP-gebaseerde container, en HTML/XML worden gedetecteerd op basis van markup of root-content. In deze fixtures won de liegende extensie dus niet.
Dan de tekstfamilie. Markdown werd alleen als text/markdown herkend wanneer de .md-extensie aanwezig en leesbaar was. Hernoem het bestand, haal de extensie weg of stuur het als stream, en in deze test viel het terug naar text/plain. CSV deed in deze bewust kleine grid hetzelfde: text/csv kwam alleen uit de .csv-glob. Geteld over unieke voorwaarden werd Markdown en CSV elk in één van vier situaties als hun eigen type opgelost; platte tekst was al text/plain, dus daar viel niets van te "collapsen". De ruwe 48-run harness blijft nuttig als herhaalbaarheidsrecord, maar niet als grotere noemer.
Eén detail werkt hier in Tika's voordeel: de liegende extensie wint ook niet. Mijn Markdown-fixture die naar .pdf was hernoemd, kwam terug als text/plain, niet als application/pdf. Tika geloofde de leugen niet; het kon de waarheid alleen niet bevestigen. Terugvallen op het bovenliggende type is een veel beter foutscenario dan zelfverzekerd een verkeerd type beweren, en dat text/markdown een gedocumenteerde 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-detectie, en bij het parsen — bevestigd doordat TextAndCSVParser in de X-TIKA:Parsed-By-keten verscheen — werd mijn kleine grid van 2 kolommen bij 3 rijen als text/plain opgelost in plaats van text/csv. Dat is één observatie op een bewust minimaal fixture. Een grotere of geciteerde CSV kan de detector prima triggeren. Ik beweer niet dat content-detectie voor CSV stuk is; ik beweer dat op deze grid de extensie was wat text/csv opleverde.
Waarom dit ertoe doet in een echte uploadpijplijn
Het concrete scenario is een uploadrouter. Stel dat je gebruikersuploads accepteert en ze op type routeert: PDF's naar de factuurparser, spreadsheets naar de grootboekimporter, en de rest naar een tekstindex. Als je op de extensie vertrouwt, komt iemand die een PDF uploadt met de naam notes.txt in de verkeerde tak terecht — en dat is nog het vriendelijke geval; de kwaadaardige versie is een polyglotbestand met een vriendelijke extensie.
Voor de binaire en markup-fixtures die hier getest zijn, routeerde Tika op basis van inhoud, zelfs nadat de bestandsnaam was verdwenen. Dat is handig wanneer een blob store of HTTP-bodyhandler die naam al heeft weggegooid. Dat resultaat zegt niets over Tika's lange staart, ambiguïteit of polyglots. De geteste text-family fixtures gedroegen zich anders: toen de pijplijn bestandsnamen wegstripte, kwamen Markdown en CSV als text/plain binnen, waardoor regels die op hun specifieke media-type vertrouwen niet meer afvuurden. Bewaar de originele bestandsnaam dus als sidecar metadata in plaats van te verwachten dat content-detectie die terug kan reconstrueren.
De ingeplante content bleef staan. --text maakte de structuur plat.
Fidelity is de tweede as, en die splitst mooi in tweeën. Ik rendeerde één canoniek document (koppen, twee alinea's, een opsomming met bullets, een genummerde lijst en een afsluitende alinea) naar HTML, Markdown, platte tekst, DOCX, PDF, RTF, ODT en XML, plus een tabeldocument naar HTML, Markdown, tekst, DOCX, CSV en XML. Veertien carrier-rendities. Elk blok heeft een unieke token — zztitle1, zzitem3, zztblcell_beta enzovoort — dus "overleefd" versus "verloren" is een exacte substring-check, geen interpretatie.
Marker-token recall kwam uit op 1.000 over alle veertien rendities. Geen enkele ingeplante token verdween: elk gemarkeerd tabelcelletje, lijstitem en elke kop was aanwezig. Drie lokale herhalingen per carrier na warming-up leverden byte-identieke --text-output op. Dit orakel zegt niets over ongemarkeerde tekens, volgorde, witruimte, Unicode-normalisatie, herhaalde content, links, headers, voetnoten of embedded objects. Het is een aanwezigheidstest per blok, geen bewijs van volledige documentfidelity.
De platte tekstoutput geeft het grootste deel van de bronstructuur op.
Dit is hoe het HTML-tabeldocument uit --text komt:
Tool Throughput
zztblcell_alpha 120
zztblcell_beta 95
Lijnen met tabs aan elkaar gekoppeld. De header-rij wordt niet als header gemarkeerd. Er is geen raster, geen celgrenzen buiten een tab, geen manier om te zien dat dit ooit een <table> was. De DOCX-tabel vlakt op precies dezelfde manier af.
Lijsten zijn subtieler, en ze splitsen op basis van wat de bron eigenlijk bevatte:
| Wat de bullet in de bron was | Carriers | Wat --text teruggeeft |
|---|---|---|
Een letterlijk teken — deze rendities schreven allemaal - als echte tekst | platte tekst, Markdown, RTF, ODT, PDF | de - blijft staan, omdat Tika gewoon tekens doorgeeft |
Echte structuur — een HTML <li>, een DOCX List Bullet-stijl | HTML, DOCX | de marker verdwijnt volledig en je krijgt alleen de itemtekst: in HTML tab-ingesprongen, in DOCX gewoon een kale regel |
Tika tekent nooit een marker opnieuw uit als die niet als tekst werd aangeleverd. Zelfde content, ander ogend resultaat.
Het Markdown-geval maakt dit goed duidelijk. 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 heeft het als tekst geparst en de bytes teruggegeven. Niets begreep die tabel.
Dus het gemeten contract is smaller: alle ingeplante markers overleefden, maar --text behield geen getypte elementen of een te reconstrueren tabelraster. Dat een parserfout noemen zou de kern missen. Platte extractie ontwijkt bewust het probleem van elementclassificatie; het kan ook niet voldoen aan een downstream consumer die juist die elementtypes nodig heeft. Als je getypeerde blokken of gereconstrueerde tabellen wilt, is --text één component van de stack, niet de hele stack. Andere Tika-handlers kunnen meer structuur blootleggen, maar die vielen buiten deze run.
De standaardkanttekening bij elk fidelity-cijfer 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 correctheid op een rommelige real-world corpus.
Metadata: genormaliseerd, en verfrissend terughoudend met verzinnen

Ik heb bekende waarden voor auteur, titel en aanmaakdatum ingebed in elke carrier die een metadata-laag heeft, en daarna gekeken wat er terugkwam.
| Carrier | author → dc:creator | title → dc:title | created → 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 timestamp van de generator zelf — niet gescoord |
ODT (meta.xml) | ✅ | ✅ | ✅ exact 2021-03-15T09:30:00Z |
| TXT / MD / CSV / RTF / XML | geen metadata-laag | — | — |
Auteur en titel werden teruggevonden op 4 van de 4 carriers met metadata, en — dit is het deel dat ertoe doet — 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-sleutel. Je schrijft dus één consumer, niet vier.
created is de eerlijke wiebel. DOCX en ODT gaven mijn exact ingebedde tijdstempel uit 2021 terug. De PDF leverde een aanmaakdatum, maar dat was de datum die mijn generatorlibrary bij het bouwen had meegegeven, niet de waarde die ik wilde inbedden — dus ik scoor die als aanwezig, niet als teruggevonden. En de formaten zonder metadata-laag gaven helemaal niets terug, wat precies het juiste antwoord is. Tika verzint geen auteur uit de tekstbody.
Er expres op stuklopen, en de triagetruc die daaruit volgt
Vier vijandige inputs. Een leeg bestand van nul bytes. Een geldige PDF-header met de body eraf geknipt. Een afgekorte DOCX-ZIP. En een UTF-8-bestand met multibyte-tekens zonder BOM en zonder encoding-declaratie. Dit zijn lokale fixture-vormen, geen Tika-drempels.
De onderliggende harness, gegenereerde fixtures, ruwe JSON, jar-checksum en environment-manifest zijn hier niet publiek gelinkt, dus een buitenstaander kan de exacte noemers niet zelfstandig reproduceren. Behandel de tabellen daarom als gerapporteerde observaties en niet als door derden verifieerbaar bewijs.
| Input | --text / --json | Wat het gooide | --detect |
|---|---|---|---|
| 0-byte bestand | exit 1, lege stdout | ZeroByteFileException: InputStream must have > 0 bytes | exit 0 → text/plain met bestandsnaam, application/octet-stream vanaf stream |
| Afgekorte PDF | exit 1, lege stdout | TikaException: TIKA-198: Illegal IOException from PDFParser | exit 0 → application/pdf |
| Afgekorte DOCX | exit 1, lege stdout | POI FATAL: "XML document structures must start and end within the same entity" | exit 0 → OOXML-type |
| UTF-8, geen BOM, niet gedeclareerd | exit 0 | niets | exit 0 → text/plain, charset UTF-8 |
Extractie faalt luid en deze fouten hebben dezelfde buitenvorm. Het 0-byte bestand, de afgekorte PDF en de afgekorte DOCX leverden elk een exception, exit 1 en lege stdout op. De CLI slikt de fout dus niet weg in een netjes leeg resultaat. Procesmatig veilig in deze gevallen — geen hang, geen segfault — maar de caller moet exitstatus en stderr controleren in plaats van alleen naar een lege string te kijken.
Detectie staat los van parsing. 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 pijplijn kan detectie dus als aparte triage-signaal gebruiken vóór of ná een mislukte parse. Of detect-first een goed default is, hangt af van de deploymentmodus: deze test heeft detect-first niet vergeleken met parse-only, en twee nieuwe CLI-JVM's zijn op volume misschien niet de juiste afruil.
Charset-detectie werkt. Het 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 pure ASCII-fixtures rapporteren charset=ISO-8859-1, wat op ASCII-bytes niet van UTF-8 te onderscheiden is. Dat is geen misser, maar een gelijkspel.
Tika naast unstructured: dezelfde bestandstypen, ander doel
Beide zijn in dezelfde onderzoeksessie getest, maar dit is een taxonomie van outputcontracten, geen symmetrische benchmark. De tools werden op verschillende uitkomsten beoordeeld.
Gerelateerde review: Unstructured review.
| Apache Tika | unstructured | |
|---|---|---|
| Waarop ik het mat | contentfidelity: ging er iets verloren? | elementclassificatiefidelity: kreeg elk blok het juiste type? |
| Resultaat | alle ingeplante markers aanwezig over veertien rendities | in de aparte classificatietest produceerde een platte-teksttabel een Table-recall van 0.000, en één kop met een werkwoord werd als narrative text geclassificeerd |
| Getypeerde elementen teruggegeven | geen — er kwam ook geen structuur terug | Title, NarrativeText, ListItem, Table — precies wat Tika weigert te doen |
| OCR | geblokkeerd op mijn host, tesseract ontbrak | geblokkeerd op mijn host, tesseract ontbrak |
Platte, marker-behoudende output versus getypeerde elementen met geobserveerde classificatiefouten. Kies op basis van wat de downstream consumer nodig heeft. Als het een zoekindex of een LLM-contextvenster is, kan platte tekst voldoende zijn. Als het op elementtype stuurt, kan Tika's --text-pad dat contract niet leveren.
We hebben geen cijfers voor gescande documenten.
Voor- en nadelen
Voordelen
- Content-type-detectie negeerde liegende bestandsnamen in 20/20 unieke voorwaarden over de vijf content-detecteerbare fixtures; dubbele stream-uitvoeringen waren het ook eens.
- Alle ingeplante markers overleefden in alle 14 carrier-rendities, inclusief de getagde tabelcellen en lijstitems.
- Herhaalbaar in drie lokale herhalingen: elke carrier gaf binnen deze omgeving byte-identieke tekst terug.
- Metadata werd over formaten heen genormaliseerd —
dc:creator/dc:title/dcterms:createdongeacht bronformaat, teruggevonden op 4/4 metadata-bearing carriers. - Echt dependency-vrij voor de formaten die ik testte: PDF-tekstlaag, DOCX, ODT, RTF en HTML parsen allemaal uit één jar zonder externe binaries.
- Draait probleemloos op OpenJDK 26 — geen beperking tot LTS.
- Detectie blijft correct (exit 0) bij afgekorte binaries, wat een betrouwbaar triage-signaal geeft wanneer parsing faalt.
- Apache-2.0, volwassen, actief onderhouden.
Nadelen
- Markdown- en CSV-identiteit hangen volledig af van de bestandsextensie; 10 van de 18 signatuurloze cellen vielen terug naar
text/plainzodra de bestandsnaam weg was of fout was. --textgeeft geen elementtypes terug; tabelrasters vlakken uit naar regels met tabs en structurele lijstmarkeringen verdwijnen.- Extractie gooit onafgevangen exceptions op lege en corrupte inputs; de twee gevallen zien er vanuit alleen de extractie-call identiek uit.
- 67 MB jar plus per-invocation JVM-cold-start in CLI-modus.
- OCR en gescande image-PDF's zijn hier helemaal niet getest — tesseract en poppler ontbraken, dus ik doe geen enkele claim over dat pad.
- Elk cijfer hier is synthetische waarheid op één machine, één versie. Werkelijke corpusnauwkeurigheid, versleutelde bestanden, ingebedde/recursieve documenten en throughput op schaal zijn niet gemeten.
Wie het wel moet gebruiken, en wie niet
Tika past wanneer je input bestaat uit bestanden die je al hebt en je output tekst plus metadata moet zijn die een machine kan indexeren. Zoekindexering, e-discovery, archiefverwerking, een corpus voeden aan een LLM, of de content-type-validatielaag van een uploadpijplijn 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 voor content die je pijplijn zich niet kan veroorloven te verliezen.
Sla het over — of beter: stop niet bij --text — als je getypeerde elementen, gereconstrueerde tabellen of documentlayout nodig hebt. Sla het over als je documenten scans zijn, ten minste totdat je tesseract hebt geïnstalleerd en je eigen cijfers hebt gedraaid, want ik heb er geen. Voor volumewerk: benchmark de library- of servermodus tegen de CLI op representatieve documenten. Processtart was zichtbaar in deze small-file-harness, maar throughput en resourcekosten zijn niet gemeten.
Eén valkuil die vaak voorkomt: als je opslaglaag bestandsnamen wegstript en je verwerkt Markdown of CSV, vertrouw er dan niet op dat Tika die van platte tekst onderscheidt. Bewaar de oorspronkelijke naam.
Alternatieven, en waar Thunderbit past
Eerst even eerlijk kaderen, want de vergelijking hier gaat over inputs, niet over kwaliteit. Tika is een gratis, Apache-2.0, self-hosted toolkit om bestanden te parsen. Bestanden die je al op schijf of in een bucket hebt. Het haalt geen pagina's op, draait geen JavaScript, omzeilt geen anti-bot en doet ook niet alsof.
Dat is precies de grens waar een beheerde web-extractieservice, inclusief onze eigen Thunderbit, in de architectuur kan passen: die haalt live pagina's op, terwijl Tika bestanden parseert die al in jouw bezit zijn. Dit artikel heeft die services niet tegen Tika gebenchmarkt, en het zijn geen vervangers voor dezelfde input.
De strakke scheiding: Tika voor documenten die je al hebt, een beheerde extraction API voor webpagina's die je nog moet ophalen. Veel pijplijnen gebruiken gewoon allebei — crawlen en extraheren aan de webkant, Tika op de PDF- en DOCX-bijlagen die terugkomen.
Als je vergelijkt binnen het bredere open-source veld, heb ik de volledige vergelijking van open-source scrapers uitgewerkt, een overzicht van de meest nuttige 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 uitleg over hoe je een site met AI scrapt.
Probeer Thunderbit voor webdata-extractie
Conclusie
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 pijplijn zich niet kan permitteren te verliezen.
De detector was het sterkste deel van deze run. Die gaf in 20 van de 20 unieke voorwaarden voor de vijf content-detecteerbare fixtures het verwachte type terug, inclusief streams zonder bestandsnaam. Alle ingeplante markers overleefden over veertien rendities, en de output herhaalde byte-voor-byte in drie lokale herhalingen. Nuttig bewijs. Nog steeds synthetisch bewijs. Dat het vanaf één jar op deze JDK draaide, zonder externe binaries voor de niet-OCR-routes die ik testte, hield de deployment aangenaam saai.
Wel goed dimensioneren. Elke tabel die je erin stopt, komt terug als regels met tabs. Elke structurele lijstmarkering 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-call nodig om ze uit elkaar te houden. En voor OCR, waar veel Tika-gebruikers juist het meest om geven, heb ik niets te bieden: ik kon het niet draaien en ga het ook niet schatten.
Binnen die grenzen doet Tika een onopvallende klus met opvallende betrouwbaarheid. Het leest de bytes, niet het label op de doos. Vraag het alleen niet welke vorm die bytes hadden.
Probeer Thunderbit voor webdata-extractie Get Started Free
Veelgestelde vragen
Detecteert Apache Tika bestandstypen correct als de extensie fout is?
Voor de vijf content-detecteerbare fixtures die hier getest zijn: ja. PDF, DOCX, RTF, HTML en XML kwamen in alle 20 unieke logische voorwaarden (30 ruwe runs met dubbele stream-uitvoeringen) op hun verwachte media type uit, ook met misleidende extensies, zonder extensie en met streams zonder bestandsnaam. Een PDF met de naam .txt werd nog steeds als application/pdf gedetecteerd. Markdown en de kleine CSV-fixture waren afhankelijk van bestandsnaam-informatie en vielen terug naar text/plain als die ontbrak of fout was.
Behoudt Tika tabellen en documentstructuur?
Niet in de hier geteste --text-modus. Tabelrasters kwamen terug als regels met tabs, zonder cel- of header-semantiek, en structurele lijstmarkeringen (een HTML <li>, een DOCX List Bullet-stijl) verdwenen. Alle ingeplante markers overleefden over alle 14 carrier-rendities, maar dat bewijst geen volledige contentfidelity, en --text geeft geen elementtypes terug. Voor getypeerde elementen of gereconstrueerde tabellen moet je een andere Tika-outputhandler testen of een ander tool ernaast gebruiken.
Kan Apache Tika OCR doen op gescande PDF's? Tika ondersteunt OCR via Tesseract, maar ik heb het niet getest, en niets van deze resultaten is een claim daarover. Tesseract en poppler ontbraken op mijn testhost, dus alle OCR- en scanned-image-routes waren al geblokkeerd vóór ze konden draaien. Er zijn hier nergens OCR-cijfers. Als OCR jouw use case is, installeer tesseract en benchmark het zelf — behandel dat deel van Tika hier als onbevestigd.
Wat doet Tika met lege of corrupte bestanden?
Het faalt luid in plaats van stil. 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 geven exit 1 en lege stdout, dus leeg en corrupt zijn vanuit alleen de extractie-call niet 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 een parse uitvoert.
Wat heeft de Tika-test niet gedekt? Vier dingen, expliciet. OCR en gescande afbeeldingen (geblokkeerd, niet getest). Nauwkeurigheid op echte corpora — alle resultaten zijn gecontroleerde synthetische fixtures met ingeplante marker-tokens, dus dit meet fidelity tegen bekende labels en niet nauwkeurigheid op rommelige echte documenten. Resourcegebruik, throughput en piekgeheugen, die ik niet heb gemeten. En de lange staart van de claim van "duizend bestandstypen": ik testte negen representatieve, dependency-vrije formaten, niet de volledige catalogus. Alles hier is Tika 3.3.2 op OpenJDK 26.0.1, macOS arm64, één machine.


