Katana is ProjectDiscovery’s crawler voor eindpuntdetectie — een Go-binary met MIT-licentie die een target pakt en URL’s en eindpunten teruggeeft voor de volgende tool in een pipeline. Je kunt ermee crawlen in een browserloze HTTP-modus of met -headless, waarbij Chromium wordt aangestuurd. In de officiële documentatie wordt headless neergezet als de optie met de hoogste dekking; deze test laat zien waarom het type eindpunt minstens zo belangrijk is als het aantal.
Ik bouwde een kleine site met drie bewust verschillende soorten eindpunten en mat per modus welke daarvan werden gevonden in v1.6.1 bij -d 4. Gewone HTML werd in alle vier configuraties volledig gevonden: 4/4 links en de volledige keten van drie stappen. Het verschil zat in eindpunten die via JavaScript-broncode of via runtime-aanpassingen aan de DOM zichtbaar werden.
In deze test vond headless de runtime-DOM-categorie die de browserloze modi misten, terwijl de standaardmodus met -jc JavaScript-literals vond die beide headless-runs misten. Geen enkele rij in de matrix van vier commando’s dekte beide categorieën af. Scope, resume en known-files bepaalden de overige praktische grenzen.
Wat katana eigenlijk is
De katana-crawler — projectdiscovery/katana op GitHub — is geschreven in Go en heeft een MIT-licentie. Ik testte v1.6.1 op 27 juli 2026; die versie is belangrijk, omdat de bevindingen over dekking en known-files hieronder specifiek zijn voor deze build.
De categorienaam is hier belangrijker dan normaal. Een endpoint-discovery crawler is geen veld-extractor. Als je een Go web crawler zoekt die productnamen en prijzen als gestructureerde JSON teruggeeft, zit je met katana op de verkeerde plek — het vertelt je zonder moeite dat /products/1138 bestaat, maar niet wat er op die pagina staat. Dat is juist de bedoeling; beoordelen op extractie zou zijn alsof je een metaaldetector recenseert op zijn vermogen sieraden te taxeren.
Het is vooral bedoeld voor offensive-security recon en automatiseringspijplijnen: STDIN erin, URL’s eruit, doorsturen naar de volgende tool. Daarom meteen de vanzelfsprekende waarschuwing: alle metingen hier zijn uitgevoerd op een fixture op 127.0.0.1 die ik zelf heb geschreven. Gebruik katana alleen op hosts die van jou zijn of waarvoor je expliciete toestemming hebt om ze te testen. Dit gaat niet over het omzeilen van beveiliging; het gaat erom hoeveel van het eindpuntenoppervlak van een site een bepaald commando echt in kaart brengt.
De drie modi, en wat elk van hen kan zien
De standaardmodus is een Go HTTP-client. Die haalt pagina’s op, parseert HTML, volgt hrefs en start nooit een browser. Snel, goedkoop, maar blind voor alles wat pas na JavaScript-uitvoering bestaat.
-jc (-js-crawl) zet een JavaScript-parser op dat browserloze pad. Het downloadt gekoppelde .js-bestanden en haalt stringliterals die op URL’s lijken uit de broncode. Geen uitvoering, alleen lezen. Er is ook -jsl (jsluice), in de README beschreven als een zwaardere parser die meer geheugen vraagt — die heb ik niet getest, dus daar kan ik niets over zeggen als het om dekking gaat.

-headless stuurt Chromium aan en voert scripts op de pagina uit. In deze test was het de enige geteste Katana-modus die het pad terugvond dat uit fragmenten werd opgebouwd en in de runtime-DOM werd ingevoegd. Dat zegt niets over wat elke parser of een toekomstige Katana-modus zou kunnen vinden.
Dan is er nog het scopemodel, en dat is het onderdeel dat ik zou onthouden vóór ik iets op productie loslaat.
| Flag | Wat het regelt | Waarden / standaard |
|---|---|---|
-fs (field scope) | welke hosts meetellen | dn, rdn, fqdn, of een aangepaste regex — standaard rdn |
-cs en -cos | URL-regexen die binnen die field scope filteren | — |
-kf | bekende bestanden: robots.txt en sitemap.xml | de README zegt dat minimaal diepte 3 nodig is |
-d | diepte | standaard 3 |
-resume | hervat een onderbroken crawl | — |
De volgorde is niet cosmetisch: die bepaalt of een host-regex een crawl groter maakt of juist stilletjes leegtrekt.
Setup: één binary, één asterisk
Drie manieren om te installeren, en maar één daarvan heeft een toolchain nodig:
| Installatieroute | Vereiste |
|---|---|
Uit bron: go install github.com/projectdiscovery/katana/cmd/katana@latest | Go 1.25 of nieuwer is de opgegeven vereiste |
| Voorgecompileerde binaries op de releasepagina | geen toolchain |
| Docker-image | geen toolchain |
Die van mij belandde in ~/go/bin/katana en meldde bij elke run Current version: v1.6.1. Tot nu toe gewoon het vertrouwde Go-verhaal: één bestand, geen runtime.
De asterisk zit bij headless, waar de browser een aparte vereiste is naast de binary:
Waar -headless draait | Wat het nodig heeft |
|---|---|
| Mijn machine | katana detecteerde automatisch een al geïnstalleerde Chromium; ik heb de browserbuild niet genoteerd en geen browserpad opgegeven |
| Een kale server, volgens de Ubuntu-instructies van het project zelf | eerst apt install google-chrome-stable, pas daarna doet headless iets |
| De Docker-route | draait headless met -system-chrome |
Op een kale server verdwijnt dat gemak. Reken dus op een browser, niet alleen op een binary, zodra -headless in je commando verschijnt.
Nog één klein ding dat handig is als je dit in CI draait: katana doet bij het opstarten een versiecheck naar GitHub. -duc schakelt die uit. Op een laptop is dat ruis; op een air-gapped of rate-limited runner is het per run een netwerkronde die je niet hebt gevraagd. In mijn timing-runs stond -duc aan, zodat de cijfers crawling meten en niet het bellen naar huis.
Hoe ik het heb getest
Drie soorten eindpunten, bewust gekozen omdat ze de modi uit elkaar trekken. Alles draait op een lokale fixture-server, en de ground truth lag vast vóór er ook maar één crawl begon, zodat recall wordt gemeten tegen een vaste set en niet tegen wat katana toevallig uitspuugde.
- Categorie A — gewone HTML.
/page/a,/page/b,/page/c, plus een keten van drie stappen/depth/1 → /depth/2 → /depth/3. Elke crawler zou deze moeten vinden. - Categorie B — literals in JavaScript-bestanden.
/api/js-endpoint-7en/api/js-endpoint-8bestaan alleen als stringliteral in een gekoppeld/static/app.js. Leesbaar zonder browser, als iets de JS tenminste leest. - Categorie C — alleen runtime-DOM. Eén pad wordt tijdens runtime opgebouwd uit fragmenten (
'endpoint' + (6 * 7)) en via script in de DOM gezet. De string/runtime-only/endpoint42verschijnt nergens aaneengesloten in bytes die de server verstuurt — niet in de HTML, niet in de JS-broncode. Alleen uitvoering onthult het.
Daarnaast waren er robots.txt, een sitemap.xml met twee <loc>-eindpunten die nergens anders voorkomen, een route die 500 teruggeeft, een doodlopende link en een link buiten scope naar een tweede server op een andere hostname.
Het instrument is bijna net zo belangrijk als de fixture: de server telt wat er echt is opgehaald, dus scope- en resume-beweringen steunen op daadwerkelijke hits en niet op katana’s eigen stdout. De ruwe runs staan vastgelegd in de benchmark-repo als je mijn rekenwerk wilt controleren.
De dekking-splitsing die niemand kwantificeert

De matrix per modus en eindpuntcategorie, bij -d 4:
| Modus | HTML-links (A) | Diepteketen (A) | JS-bestand-literals (B) | Runtime-DOM (C) |
|---|---|---|---|---|
| standard | 4/4 | 3/3 | 0/2 | niet gevonden |
standard -jc | 4/4 | 3/3 | 2/2 | niet gevonden |
-headless | 4/4 | 3/3 | 0/2 | gevonden |
-headless -jc | 4/4 | 3/3 | 0/2 | gevonden |
Lees de laatste twee kolommen als een paar en het probleem springt meteen in het oog. Categorie B werd door precies één configuratie gevonden: standaardmodus met -jc. Categorie C werd door precies twee configuraties gevonden: beide headless-runs. Er is geen enkele rij met een treffer in beide kolommen. De volledige matrix staat in discovery-summary.json, waar het berekende veld headless_jc_covers_both false is.
De praktische consequentie is dat “gewoon headless gebruiken voor betere dekking” hier onvolledig was. Headless voegde categorie B niet toe boven op het standaardresultaat; het herstelde categorie C terwijl categorie B juist ontbrak. Voor volledige dekking van alle ingeplante categorieën in deze fixture waren twee crawls en een merge nodig:
katana -u https://target.example -jc -d 4 -silent -o pass-jc.txt
katana -u https://target.example -headless -d 4 -silent -o pass-headless.txt
sort -u pass-jc.txt pass-headless.txt > endpoints.txt
De rij -headless -jc is degene waar ik het liefst een upstream-antwoord op zou zien. Het toevoegen van de JavaScript-parser aan de headless-run leverde niets extra’s op — nog steeds 0/2 voor categorie B, in elke run, ook bij een verse reproductie. Ik rapporteer het gedrag; ik claim niet dat ik het mechanisme heb uitgezocht. Ik heb katana’s interne werking niet geprofileerd om te achterhalen waarom het browserpad geen JS-bestandsliterals meer bijdraagt. Zie dit als een reproduceerbare observatie en een goede GitHub-issue, niet als een diagnose. (Wel het vermelden waard: de combinatie -hl -jc sloot in v1.6.1 op macOS ARM netjes af met returncode 0, wat historisch niet altijd zo was.)
De officiële docs beschrijven headless als betere dekking, en dat gold hier inderdaad voor de runtime-gerenderde categorie. De handleiding vermeldde deze splitsing tussen source-literals en runtime-DOM niet expliciet, dus zie de matrix als een reden om beide paden op je eigen eindpuntcategorieën te testen, niet als een universele taxonomie.
Wat headless kost aan wall time
Drie opeenvolgende runs per modus op een verder inactieve machine:
| Modus | p50 | min–max | gemiddelde |
|---|---|---|---|
| standard | 13.08s | 13.07–13.17s | 13.11s |
-headless | 66.82s | 66.78–67.68s | 67.09s |
Dat is een verhouding van 5,1x, met bereiken die elkaar niet eens in de buurt raken — mijn traagste standard-run (13.17s) was nog steeds meer dan 53 seconden sneller dan mijn snelste headless-run (66.78s) (cost-summary.json). Dit is geen meetruis.
Een kanttekening bij die 13 seconden: mijn fixture bevat bewust een 500-route en een dode link, en de standaardmodus wacht op beide de default -timeout 10 retry-tail uit. Ik heb de timeout niet aangepast om de snelle modus mooier te laten lijken; daardoor zou een getunede standard-run de kloof waarschijnlijk juist groter maken in plaats van kleiner.
De ratio is een lokaal capaciteitsignaal, geen productieschatting. Echte targets verschillen in latency, fouten, scriptwerk en scheduling, terwijl deze fixture een standaard timeout-tail bevat. Gebruik het gemeten verschil van 5,1x om te bepalen of headless een eigen budget en targetsubset verdient, en benchmark dat plan vervolgens op representatieve, geautoriseerde hosts.
Scope bleef staan, maar één flag deed stilletjes niets
De scopetest gebruikte twee servers: de primaire op 127.0.0.1 en een tweede die bereikbaar was als localhost op een andere poort, en die een pad serveerde dat alleen daar bestond. Een hit op dat pad bewijst dus dat de host buiten scope echt is opgehaald, en niet alleen geprint.
| Configuratie | Host buiten scope opgehaald? | Hits op de tweede server |
|---|---|---|
standaard (-fs rdn) | nee | 0 |
-fs fqdn | nee | 0 |
-cs localhost | nee | 0 |
| `-fs '(127.0.0.1 | localhost)'` | ja |
Scope-discipline is goed nieuws: standaard bleef katana netjes binnen de deur, en verbreden vroeg om een expliciete actie. Dat is precies het juiste standaardgedrag voor een tool die je op andermans infrastructuur inzet.
De interessante rij is -cs localhost. Die verbreedde de crawl niet naar de tweede host — en gaf ook helemaal geen URL’s terug. Omdat -cs binnen de field scope filtert, en die scope nog steeds de primaire host was, matchte de regex niets en gaf de crawl een lege set terug in plaats van een fout. Als je ooit een regex hebt geschreven voor crawl-scope met de naam van een host die je wilde meenemen en naar een leeg outputbestand zat te kijken, dan is dit het mechanisme (scope-summary.json). Wil je een host toevoegen, stel dan -fs in. Wil je binnen bestaande hosts beperken, gebruik dan -cs/-cos.
Resume is grover dan de flag doet vermoeden
De README beschrijft de flag als -resume string resume scan using resume.cfg, wat klinkt als een bestand in je werkmap. Dat is het niet. Op mijn machine werd het checkpoint geschreven naar ~/.config/katana/resume-<xid>.cfg — gemeten, niet van een documentatiepagina gehaald, want de docs noemen geen pad.
Wat erin staat is de belangrijkere verrassing. Het bestand bevatte een InFlightUrls-map met precies één ding: de seed-URL. Niet de bezochte set, niet de frontier. Dit gebeurde toen ik een crawl met SIGINT onderbrak na drie seconden en daarna hervatte:
| Run | Aantal unieke paden |
|---|---|
| Volledige baseline-crawl | 11 |
| Opgehaald vóór de onderbreking | 10 |
| Opnieuw opgehaald door de resume-run | alle 11, inclusief alle 10 die al klaar waren |
Resume bereikte wel dezelfde uiteindelijke set eindpunten, dus er is niets stuk. Maar de granulariteit van het checkpoint is per input-seed, niet per URL — de dedupe-filter in geheugen wordt nooit gepersisteerd, dus een hervatte single-seed crawl doorloopt die seed opnieuw vanaf nul (resume-summary.json). Als je katana een lijst van 500 hosts geeft, zou resume je de hosts moeten besparen die volledig klaar waren; dat multi-seed-gedrag volgt uit de opslag van de staat, maar ik heb alleen de single-seed-case gemeten. Werk je diep in één enorme site, dan koop je met resume correctheid, geen tijd.
Known files: gevraagd, daarna laten vallen

-kf all -d 3 vroeg inderdaad beide bestanden op — robots.txt en sitemap.xml verschenen in de hitlog van de server — en vond daarna 0 van de 2 eindpunten terug die in de <loc>-elementen van die sitemap stonden. Recall 0.0.
Voordat ik dat als beperking bestempelde, probeerde ik te bewijzen dat het aan mij lag. Elke variatie leverde hetzelfde op:
| Geprobeerde variatie | Herstelde sitemap-<loc>-eindpunten |
|---|---|
-kf all | 0/2, recall 0.0 |
-kf sitemapxml | 0/2, recall 0.0 |
-kf robotstxt | 0/2, recall 0.0 |
| diepte 3 | 0/2, recall 0.0 |
| diepte 4 | 0/2, recall 0.0 |
| diepte 5 | 0/2, recall 0.0 |
met -jc toegevoegd | 0/2, recall 0.0 |
direct gezaaid op /sitemap.xml | 0/2, recall 0.0 |
De gedocumenteerde eis — gebruik -kf, ga minstens drie niveaus diep — werd elke keer gehaald. Dit is dus niet het verhaal van een ontbrekende flag.
De nuttige conclusie komt eerst: ga op deze IP-literal-fixture er niet van uit dat het opvragen van known files betekent dat de <loc>-URL’s ook echt zijn toegevoegd aan de crawl. Verifieer recall, of extraheer die URL’s zelf en gebruik ze als seed.
De codepath in v1.6.1 past bij deze observatie, maar ik heb het tijdens de run niet geïnstrumenteerd. In sitemapxml.go in v1.6.1 bouwt NewNavigationRequestURLFromResponse <loc>-navigatieverzoeken vanuit een response zonder ingevulde RootHostname. Het verzoek komt daarna bij ValidateScope terecht; in scope.go in v1.6.1 vergelijkt de IP-literal-branch de host van de URL met die lege root en kan die worden afgewezen. Het aangepaste -fs '(127.0.0.1|localhost)'-commando nam in een aparte scopetest een andere scope-branch, dus dat is een door de bron voorspelde redding, geen gemeten workaround voor -kf. Een bevestigingspoging werd op deze host geblokkeerd door af en toe falend dialen in de known-files-client; het gerapporteerde resultaat blijft daarom 0/2.
Wat ik in productie echt zou doen, totdat iemand de flag bevestigt: haal de sitemap zelf op, extraheer de <loc>-URL’s en geef die als seed-lijst mee aan katana. Twee regels shell, zonder scope-validatie.
Eén ding werkte precies zoals beloofd en verdient een losse zin: de 500-route en de dode link werden opgehaald, gelogd en daarna keurig overgeslagen. Elke browserloze run eindigde met returncode 0. Een crawler die op de eerste fout stopt is onbruikbaar zonder toezicht, en katana doet dat niet.
Een target-specifieke dekkingstest vóór deployment
De fixture-matrix is vooral nuttig als sjabloon om je eigen geautoriseerde targets te testen. Definieer eindpuntcategorieën vóór je Katana draait: gewone links, literals in gekoppelde scripts, routes die alleen na uitvoering ontstaan en entries uit known files zijn vier redelijke beginbakken. Houd per categorie een kleine set ground truth aan. Zonder die voorafgaande lijst kan een groter stdout-bestand eruitzien als betere dekking, terwijl een categorie in werkelijkheid verdwenen is.
Meet browserloze en headless paden eerst als afzonderlijke runs. Sla de exacte commando’s, Katana-versie, browserbuild, returncodes en outputs op. Normaliseer en diff de sets eindpunten in plaats van alleen regels te tellen. Als standaard -jc op jouw sample niets unieks toevoegt, kan een headless-only beleid voldoende zijn; als de sets uiteenlopen zoals hier, houd de twee passes gescheiden en merge pas na het verzamelen. Het toevoegen van beide flags aan één commando hoeft niet gelijk te staan aan de unie, totdat een target-specifieke diff dat bewijst.
Valideer scope met bewijs buiten katana’s output. Zet een canary-URL op een host die buiten scope moet blijven en controleer de requestlog van die server. Test ook een bedoelde tweede host als de crawl juist moet verbreden. De -cs localhost-run hier leverde een lege output op omdat content-scope-filtering de field scope niet uitbreidde; de aangepaste -fs '(127.0.0.1|localhost)'-aanroep maakte wel contact met de tweede server. Het is belangrijk om de exacte regex vast te leggen, omdat één teken verschil niet alleen de weergave maar ook de regex zelf kan veranderen.
Test onderbreking en known files los van discovery recall. Voor resume onderbreek je een representatieve seed na enkele pagina’s, sla je het aangemaakte checkpoint-pad op en tel je hoeveel afgeronde URL’s opnieuw worden opgehaald. Voor -kf controleer je zowel dat robots/sitemap zijn opgevraagd als dat de ingeplante <loc>-URL’s daadwerkelijk zijn ingepland. Dat zijn verschillende beweringen. In deze fixture werden de bestanden opgehaald terwijl de twee sitemap-eindpunten ontbraken, dus zowel requestlogs als endpoint-output waren nodig om de grens te zien.
Stel tenslotte een lokale kostenbasis vast met opeenvolgende runs op een verder inactieve machine en herhaal daarna op representatieve hosts. Bewaar minimum, maximum en mediaan, niet alleen een vermenigvuldigingsfactor. De factor 5,1x hier bevat dit fixture-gedrag rond fouten en timeouts; het zegt dat headless een eigen budget verdient, niet hoe lang een productie-inventarisatie duurt.
Voor- en nadelen
Voordelen:
- Perfecte recall op gewone HTML in elke modus — 4/4 links en de volledige 3/3-diepteketen, zonder configuratie.
-jcwerkt echt browserloos: 2/2 eindpunten hersteld uit stringliterals in een gekoppeld JS-bestand, zonder browserkosten.-headlessis de enige modus die een eindpunt vond dat tijdens runtime is opgebouwd — een categorie die per definitie onzichtbaar is voor bronparsing.- De standaard scope-instellingen zijn conservatief. De host buiten scope werd nooit opgehaald onder default,
-fs fqdnof-cs. - Eén Go-binary, MIT-licentie, voorgescompileerde builds en een Docker-image, met pipeline-vormige I/O.
- Robuust bij fouten: 500’s en dode links stoppen de crawl niet.
Nadelen:
- Geen enkele aanroep dekte zowel JS-bestand- als runtime-DOM-eindpunten af. Volledige dekking vereist twee runs en een merge.
-jcleverde onder-headlessniets op — 0/2 voor categorie B in elke headless-run.- Headless kost 5,1x zoveel wall time (66.82s versus 13.08s p50, niet-overlappende bereiken).
-resumecrawlt afgeronde pagina’s binnen één seed opnieuw. Het herstelt de eindpuntset, niet de verstreken tijd.- Known files vroegen robots.txt en sitemap.xml op, maar haalden 0/2 sitemap-
<loc>-eindpunten op tegen een IP-target. - Headless vereist stilzwijgend een Chromium op de machine; het verhaal van “één binary” stopt bij de browser.
- Alleen discovery. Geen gestructureerde extractie, geen contentconversie, geen veldschema.
Niet getest, en dus buiten wat deze cijfers dekken: -jsluice, een aparte test op dieptebeperking bij -d 1/-d 2, multi-seed resume, automatisch formulieren invullen en een echte JavaScript-zware of afgeschermde productiesite. Alle cijfers komen van één machine (macOS arm64) op een lokale fixture.
Voor wie het is, en wie het beter kan overslaan
Als jouw werk bestaat uit het samenstellen van een inventaris van eindpunten op infrastructuur waar je toestemming voor hebt, dan heeft katana precies de juiste pipeline-vorm: STDIN/STDOUT, een distributable binary en zowel browserloze als browser-ondersteunde modi. Voor deze fixture was een twee-pass merge nodig voor de ingeplante categorieën; of jouw targets beide passes nodig hebben, moet je vaststellen met representatieve pagina’s.
Sla het over als je data wilt en geen adressen. Katana geeft je nooit een tabel met producten; het geeft je de URL’s waar producten mogelijk staan, en iets anders doet de extractie. Sla het ook over als je één commando wilt dat compleet is — de twee-pass merge werkt prima in een pipeline, maar is irritant aan een prompt. En als je enumeratie steunt op sitemap-<loc>-eindpunten terwijl je IP’s target, verifieer dan eerst wat je echt krijgt voordat je de output vertrouwt, want in mijn fixture leverde dat pad niets op.
Alternatieven, en de extractiegrens
Katana is gratis, MIT-gelicenseerd en self-hosted. Discovery, moduskeuze, browserinzet en samenvoegen van resultaten blijven aan jouw kant van de grens.
Binnen open source zijn de nuttige vergelijkingen eerder taakgericht dan taalgericht. Colly is de andere Go-optie, maar het is een library die je met je eigen callbacks compileert en het rendert helemaal geen JavaScript. Crawl4AI draait een echte browser en produceert Markdown voor LLM-pijplijnen, wat een heel ander soort output is. Als je meerdere van deze opties tegelijk afweegt, zet onze open-source scraper round-up de categorieën naast elkaar.
Openbaarmaking: Thunderbit is het product van de uitgever en is niet getest in deze Katana-fixture. Het zit stroomafwaarts in de categorie beheerde extractie: pagina’s worden omgezet in tekst of gestructureerde records in plaats van het eindpuntenoppervlak van een geautoriseerd target te inventariseren. Een workflow kan beide categorieën gebruiken, maar deze review levert alleen bewijs voor Katana’s discovery-gedrag.
Probeer Thunderbit voor webdata-extractie
Conclusie
Gebruik katana wanneer het eindresultaat een lijst met eindpunten is voor targets die je mag crawlen, en wanneer je de dekking per modus op die targets kunt valideren. In deze fixture vond standaard -jc de ingeplante JavaScript-bestand-literals, terwijl headless het runtime-DOM-eindpunt vond; de geteste browserloze modi van Katana vonden dat runtime-pad niet. De standaard scope liet bovendien de tweede host met rust, en browserloze runs gingen gewoon door na de 500 en de dode link.
De kanttekeningen zijn operationeel: voor gemengde eindpuntcategorieën kan een twee-pass merge nodig zijn, headless kostte ongeveer vijf keer zoveel lokale wall time, single-seed resume haalde afgeronde paden opnieuw op, en known-files kwam uit op 0/2 tegen het IP-target. Dit zijn v1.6.1-resultaten van een fixture, geen garanties voor elke site. Ze zijn wel genoeg om de checks te bepalen die een productie-evaluatie moet herhalen.
Probeer Thunderbit voor webdata-extractie Get Started Free
FAQ’s
Waar slaat katana zijn resume-bestand op, en slaat hervatten al gecrawlde pagina’s over?
Het checkpoint kwam terecht in ~/.config/katana/resume-<xid>.cfg, niet in een resume.cfg in de werkmap zoals de helptekst van de flag doet vermoeden. En nee, het slaat afgeronde pagina’s niet over: het bestand bewaart alleen de seed-URL’s die nog bezig waren, dus een hervatte single-seed crawl haalde alle 11 baseline-paden opnieuw op, inclusief de 10 die al klaar waren. Je krijgt wel dezelfde uiteindelijke eindpuntset, maar niet de bespaarde tijd.
Waarom vroeg -kf all mijn sitemap.xml op, maar crawlde het de URL’s daarin niet?
Tegen een IP-target is dit een grens van scope-validatie, geen fout van een flag. Katana’s sitemap-parser bouwt elke <loc>-aanvraag zonder de root-hostname mee te nemen, en de DNS-scope-check voor IP-literals vergelijkt de host van de URL vervolgens met die lege root, wat faalt en de URL weggooit. Dat bleef op 0 recall staan voor elke flag-, diepte- en seedingvariatie die ik probeerde. Een aangepaste host-regex via -fs volgt een andere validatiebranch en is de fix die de bron voorspelt — maar ik kon dat niet bevestigen met -kf op mijn machine, dus beschouw het als onbewezen. Zelf de <loc>-URL’s extraheren en die als seed aan katana geven is de aanpak die ik vandaag zou vertrouwen.
Wat moet ik bewaren bij een rapport over een Katana-dektest?
Noteer de exacte Katana-versie en het commando, inclusief de byte-voor-byte -fs-expressie; definieer eindpuntcategorieën vóór de run; bewaar server-side hitlogs naast stdout; en scheid gemeten gedrag van hypotheses op basis van de broncode. Voor headless-runs moet je ook de browserbuild vastleggen — dat heb ik in deze test niet gedaan, wat de reproduceerbaarheid beperkt.
Moet ik -jc, -headless of allebei gebruiken?
Kies op basis van de eindpuntcategorieën die je nodig hebt. In deze fixture vond standaard -jc de literals in een JavaScript-bestand, terwijl headless het eindpunt vond dat in de runtime-DOM werd geplaatst. Geen van beide modi dekte alleen alles af, dus voor gemengde targets was een twee-pass-run met deduplicatie de verdedigbare keuze.
Stopt één mislukte URL de crawl? Niet in deze gecontroleerde run. Katana ging door na zowel een 500-respons als een dode link en gaf nog steeds de andere bereikbare paden terug. Dat is geen vervanging voor productie-foutregistratie: houd logs bij van mislukte requests en bepaal een acceptabel foutpercentage, zodat een gedeeltelijk geslaagde crawl niet voor volledige dekking wordt aangezien.


