← All guides
Start here

Which Extraction Method Should You Use?

A decision path through all six extraction methods, with the question to ask at each fork and the failure mode of each wrong turn.

Verid Guides·8 min read

Why this guide exists

Every monitor needs an extract_config, and every extract_config names a method. Verid supports six of them, and picking the wrong one is the single most common reason a new monitor sits there doing nothing useful: a selector that never matches, a hash that fires on every page load, an AI prompt burning quota for a value CSS could have grabbed for free.

This guide is one decision path. Ask the questions in order; the first "yes" is your method.

The decision path

  1. Does the URL return JSON? (Content-Type: application/json, or you're hitting an API endpoint directly) - use JSONPath.
  2. Does the page have clean, semantic class names or IDs around the value? - use CSS selector.
  3. Do you need to match by text content, walk up to a parent, or read an attribute value (href, data-price) rather than an element's text? - use XPath.
  4. Does the value only exist in the raw source - inside a <script> tag, a template literal, an inline string - with no clean element to select? - use Regex.
  5. Do you not know, or not care, exactly what changes - you just want to know that the page moved? - use Full Page Hash.
  6. Is the markup unstructured, shifting, or does the value require reading and interpreting, not just locating? - use AI / LLM extraction.

Each fork below explains the question, why it's the right test, and what happens when you pick the wrong branch anyway.


Fork 1 - JSON response → JSONPath

If the monitor's URL is a JSON API - a GitHub releases endpoint, an npm registry lookup, a weather API, any endpoint you'd otherwise hit with curl - JSONPath is almost always correct. It parses the raw response body as JSON and applies an expression like $.tag_name directly to the structure, with no HTML in between.

Wrong-turn failure mode: pointing CSS or XPath at a JSON endpoint fails outright, because there's no DOM to select against - the parser has nothing to walk. Less obviously, forcing fetch_mode: "browser" on a JSON endpoint doesn't help either: a browser renders the JSON as an HTML page wrapping the text, which JSONPath then can't read. JSON extraction should stay on the static fetch path.

See JSONPath extraction.

Fork 2 - Clean class names → CSS

For rendered HTML with semantic class names or IDs around the value (.current-price, #stock-status), CSS selectors are the fastest method to write and the cheapest to run. If you can find the element in DevTools with a one-click "Copy selector," this is your method.

Wrong-turn failure mode: a selector that matches nothing returns an empty field rather than an error, so a broken CSS selector on a JavaScript-rendered page looks like "monitor is working, value never changes" until you notice the field is empty on every run. CSS also only ever returns the first matching element - if the value you want is the second or third match, the field silently captures the wrong one instead of failing.

See CSS selector extraction.

Fork 3 - Needs text matching or parent traversal → XPath

Reach for XPath when CSS genuinely can't express the query: matching an element by its text content (find the <td> next to the one that says "Total Price"), walking up to a parent or ancestor, or reading an attribute value (href, data-id, aria-label) instead of text content. XPath 1.0 can do all three; CSS selectors can do none of them.

Wrong-turn failure mode: using XPath where CSS would do isn't wrong, exactly, but it costs you nothing to prefer CSS when a class name is available - XPath expressions are harder to read back later and easier to break with a small markup change, since a longer traversal path has more nodes that can move.

See XPath extraction.

Fork 4 - Value only exists in raw source → Regex

When the value you want isn't in a clean DOM element at all - it's embedded in a <script> tag as a JS literal (window.__APP_VERSION__ = "2.4.1"), or it's a count of how many times a tag appears (<loc> in a sitemap) - regex against the raw response body is the only method that can reach it. Regex runs before any DOM parsing happens, so it sees text CSS and XPath never do.

Wrong-turn failure mode: regex is the most flexible method and also the easiest to make brittle. A pattern with no capture group stores the match count, not a value - fine for "how many <loc> tags," wrong if you meant to capture a price. And a pattern anchored too tightly to surrounding text breaks the moment that surrounding text changes, even if the value itself didn't move.

See Regex extraction.

Fork 5 - Don't know or don't care what changed → Full Page Hash

Full Page Hash needs no selector at all: Verid strips known noise (scripts, styles, CSRF tokens, nonces, comments), hashes what's left, and alerts when the hash differs from last time. It's the fastest method to set up and the right one for "tell me if this status page or announcement page changes at all."

Wrong-turn failure mode: the same normalization that strips CSRF tokens can't strip a rotating ad, a "you may also like" carousel, or a live visitor counter, so a full-page hash on a page with any of that content fires constantly on content you don't care about. And because it's a hash, an alert never tells you what changed - only that something did. If you need the actual new value, this is the wrong method regardless of how noisy the page is.

See Full Page Hash.

Fork 6 - Unstructured or shifting markup → AI extraction

When the page is rendered by JavaScript with nothing usable in the raw HTML, the markup reshuffles often enough that selectors keep breaking, or the value requires actually reading and interpreting the content rather than locating a fixed spot - "the current system status in one word," "the names and prices of all featured products" - AI extraction is the method built for it. You write a plain-English prompt instead of a selector, and Verid sends the page content to an LLM that returns structured JSON.

Cost note: unlike the other five methods, AI extraction meters against your plan's monthly LLM-call quota: 50 calls/month on Free, 250 on Lite, 500 on Starter, 5,000 on Pro, 25,000 on Scale. Results are cached, so an unchanged page doesn't spend a second call - but a page that changes on every check will burn through a Free plan's 50 calls in under two days on an hourly interval. If a selector-based method can reach the value at all, it's both free and faster; save AI for the pages where it genuinely can't.

See AI / LLM extraction.


When two methods both look right

A few cases are genuinely ambiguous, and the tie-break is usually cost and stability rather than capability:

  • CSS vs. XPath, both would work: prefer CSS. It's more readable later and there's no upside to XPath if you don't need what only XPath can do.
  • Regex vs. AI, on messy raw source: if the value follows a predictable text pattern (a version string, a price format), regex is free and instant. Reach for AI only once the pattern itself stops being predictable.
  • Full Page Hash vs. a scoped method: if you catch yourself wanting Full Page Hash but only because "I don't want to write a selector," write the selector anyway - a hash can't tell you the new price, and it will alert on the page's rotating content whether you meant it to or not.

None of this is permanent. A monitor's extraction method is one field in its config - if a Full Page Hash monitor turns out too noisy, or a CSS selector turns out too brittle, the fix is editing the monitor and testing the new config against the live page before saving, not living with the wrong method.

What to read next

Ready to try it? Point Verid at your URL and get a signed alert on every change. 5 monitors free, no credit card.

Try Verid for free

5 monitors, no credit card required.