Safeguard
Developer Tools•

Is the AJAX spider still the right crawler for a DAST scan?

ZAP now recommends its Client Spider over the AJAX spider for modern web apps. What a browser-driven crawler does, and how to check what yours covered.

Safeguard Security Team
7 min read

For one widely used open source scanner, no. Its documentation now says the AJAX spider is no longer the recommended option for crawling modern web apps and recommends the Client Spider instead. Whatever tool you use, check its crawler against your own app, because crawl coverage sets the ceiling for everything else.

Why the crawler matters most

A scanner can only test what it finds. If the crawl misses the checkout flow or the admin area, no attack rule ever runs there. A clean report then means "clean where it looked". Teams spend hours tuning attack rules and none checking whether the crawler reached the routes.

Definitions

  • Traditional spider: fetches pages and follows links in the HTML. Fast, but blind to routes built by JavaScript.
  • Browser-driven crawler: loads pages in a real or headless browser, runs the scripts, clicks elements and records the requests that result.
  • Client-side crawler: a newer design that inspects what happens in the browser and records the routes and calls it finds.

What the docs say

The ZAP AJAX spider page carries the note that the AJAX spider is no longer the recommended option for crawling modern web apps, and that the Client Spider is now recommended. ZAP's baseline script documentation shows the transition in its options: a flag to use the modern spider in addition to the traditional one, with the AJAX spider as the default and an option to use the client spider instead. Details change between releases, so read the current documentation for the version you run.

How to check crawl coverage

  1. List your routes. Take them from the router file, the API definition or the sitemap.
  2. Run the crawl alone, before any attack phase.
  3. Compare. For each route, mark found or missed.
  4. Look for patterns. Missed routes behind a login, behind a button click, or behind a dynamic URL point to different fixes.
  5. Add seeds. Feed missed routes in by hand, or import an API definition.
  6. Fix authentication first. Many "missed" routes are simply behind a login the crawler lost.
  7. Rerun and recompare. Record the coverage percentage.

Common reasons a crawler misses pages

SymptomLikely causeFix
Only the home page foundLinks built by JavaScriptUse a browser-driven crawler
Pages behind login missingSession lost, or logout link followedVerify login, exclude logout
Deep menu items missingNeeds clicks or hoverRaise crawl depth and time
API calls missingNot triggered by UIImport the API definition
Pages found but forms never testedTokens or validationSee anti-CSRF handling

Setting time limits

Browser-driven crawling is slower than link following. Give it enough time to finish, and note when it stops because of a limit. A crawl that hit its limit is an incomplete crawl.

What to record

Note the crawler type and version, depth and time settings, and the number of routes found against expected. That one line is the most useful context for any later report.

A worked example

A team scans a single-page app. The app has 85 routes defined in its router file. They run three crawls in a test environment and count the routes found.

CrawlSetupRoutes foundNotes
ALink-following spider only6Most routes are built by script
BBrowser-driven crawler, default depth, no login31Public pages found, protected ones missed
CBrowser-driven crawler with login verified and logout excluded72Remaining 13 need clicks on nested menus

The counts are illustrative. The pattern is typical. The first big gain comes from using a browser-driven crawler, and the second from fixing authentication. The last gap is closed with depth, time and manual seeds.

For crawl C, the team verified the login by checking for an element that only appears when signed in. They also excluded the logout path, since a crawler that follows a logout link loses its session and quietly finishes the crawl as an anonymous user.

Closing the last gap

  1. List the 13 missed routes and look for a shared trait. Here they all sit behind a nested menu that opens on hover.
  2. Raise crawl depth and the time limit, and rerun.
  3. Seed any remaining routes by hand from the router file.
  4. Add the router file as a standing check: a small script compares routes in code with routes the crawler found, and fails if the gap grows.

Choosing a crawler for a new app

QuestionIf yesIf no
Is the front end built with a script framework?Use a browser-driven crawlerA link-following spider may be enough
Is there an API definition?Import it as a second source of routesCapture traffic from tests or a proxy
Does the app need a login?Verify login and session checksSkip
Are there infinite lists or calendars?Set depth and count limitsSkip

Why tool documentation matters

Crawler recommendations change. The ZAP documentation shows how: the AJAX spider is now described as no longer the recommended option, with the Client Spider recommended instead. Teams that never reread documentation keep using older settings for years. Put a quarterly reminder on the calendar to read the release notes of your scanner and rerun your coverage check.

Infinite spaces and traps

Some apps generate endless URLs, such as calendars that let you click to next month forever. A crawler can spend its whole time budget there. Use exclusion patterns and depth limits, and review the crawl log for repeated URL shapes.

Report the coverage

Put the crawl coverage number at the top of every scan report. Readers should see "72 of 85 known routes visited" before they see a finding count. It frames the whole result honestly.

Where Safeguard fits

Crawl coverage is a web testing matter. For the dependencies that your front end and back end ship, Safeguard offers SBOM and dependency scanning with reachability analysis, and a free scan at gold.safeguard.sh/scan.

Try it yourself

Click through it at your own pace, or open it full screen.

Look at how many pages the scan discovers before testing begins.

Quick check

How do I know my crawler found everything?

Compare its results with a list of your real routes. Missing routes were never tested.

Should I switch crawlers right away?

Test the new one on a copy of your app first and compare coverage with your current results.

What if my app has no list of routes to compare against?

Build one from the router file, an API definition, the sitemap or captured test traffic. Even an imperfect list shows large coverage gaps.

Sources

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.