Skip to main content

Verifying Freshness and Liveness

Understand the difference between content freshness and whether the state represented by a page is current
5 min read

A successful scrape tells you what the page returned. It does not prove that the state represented by the page is current. These are two separate questions.

  • Freshness → Is this content recent, or a copy reused from Firecrawl's cache? Controlled by maxAge.
  • Liveness → Is the underlying thing still real and active? Your application decides this from the available evidence.

This guide explains the difference, walks through the maxAge tradeoff, and gives a checklist and worked example for freshness-sensitive actions.

Quick Comparison#

FreshnessLiveness
QuestionIs this content recent, or reused from cache?Is the object the page describes still active?
You control it withThe maxAge request parameterYour own domain logic
Firecrawl reportsmetadata.cacheState ("hit" or "miss"), and metadata.cachedAt on a hitNothing directly — only page evidence
Evidence you getWhether the response came from cachePage content, metadata.statusCode, and metadata.url vs metadata.sourceURL
Settled by an HTTP 200 with content?No — a 200 says nothing about how recent the content isNo — a 200 only describes the page response

The Freshness Tradeoff (maxAge)#

Firecrawl caches previously scraped pages and returns a recent copy when one is available, which cuts latency. maxAge is the maximum age, in milliseconds, of a cached copy that Firecrawl may return instead of retrieving the page again.

  • Omit maxAge: Firecrawl may return recently cached content. The default window is 2 days; Firecrawl may use a different window for some sites.
  • Set maxAge: 0: Firecrawl skips the cache for that request and retrieves the page. This trades latency and reliability for a fresher retrieval.

Keep caching on by default. Pay the maxAge: 0 latency cost only for the reads where staleness would cause a wrong or costly decision — it does not change what the page costs you in credits.

metadata.cacheState is returned when Firecrawl considered its cache for the request, so it is a useful check while you tune maxAge. It is not part of a maxAge: 0 response, because that request skips the cache altogether.

For caching mechanics, common maxAge values, cache-hit matching rules, and the request options that bypass caching automatically, see Faster Scraping.

Where maxAge Applies#

EndpointBehavior
/scrapemaxAge is honored on the request body
/crawl, /batch/scrapemaxAge is honored inside scrapeOptions
/searchSearch applies its own freshness window to the pages it scrapes, so maxAge in scrapeOptions does not take effect
/parse/parse always processes the file you supply and never serves or stores cached content, so maxAge and storeInCache have no effect

If you need a fresh retrieval of a page you found through /search, scrape that URL again with /scrape and maxAge: 0.


Freshness Is Not Liveness#

Even with maxAge: 0, the result only tells you what the page returned on that retrieval. A page can return HTTP 200 with content while representing an outdated, unavailable, or otherwise changed state.

So neither the status code nor the presence of content settles liveness. Liveness is a conclusion your application draws from source-specific evidence.


Freshness-Sensitive Action Checklist#

Before an action that depends on current state, treat scrape output as evidence, not proof:

  1. Use maxAge: 0 for the final retrieval so the response is not served from cache.
  2. Do not treat HTTP 200 or non-empty content as proof of liveness.
  3. Inspect rendered content and redirect evidence. metadata.sourceURL is the URL you requested; metadata.url is the URL the engine reports for the response. When the two differ, it can indicate a redirect to a different resource. Matching values do not prove that no redirect occurred.
  4. Prefer source-specific APIs or identifiers where available — they often expose an explicit status that a rendered page hides.
  5. Treat inconclusive evidence as unknown, and stop before the expensive or irreversible step, rather than assuming active.

Worked Example: Collect Current Page Evidence#

Skip the cache, then collect the rendered content and response metadata for your application's own validation rules. The scrape supplies evidence; it does not decide the domain-specific state.

The important boundary is after collection: Firecrawl supplies page evidence; your application interprets that evidence using source-specific rules. If those rules are inconclusive, keep the state unknown.


Recommendations by Scenario#

ScenarioRecommended approach
Read product copy, docs, or reference contentOmit maxAge and use the default cache window
Dashboard or report refreshed on a scheduleNon-zero maxAge sized to your refresh interval
Final check before an action that depends on current statemaxAge: 0 to skip the cache + the checklist above
Confirming an object is truly still activePrefer the source's API or status field; treat a scrape as evidence only
Ambiguous rendered page (200 but no positive signal)Classify as unknown; stop before the irreversible step

Key Takeaways#

  1. Freshness and liveness are different questions. maxAge controls freshness; liveness is a decision you make from evidence.

  2. HTTP 200 plus content does not prove that the represented state is current.

  3. For freshness-sensitive actions, use maxAge: 0 and follow the checklist. Inspect the rendered content, compare metadata.url against metadata.sourceURL for possible redirect evidence, and prefer source-specific APIs.

  4. Treat inconclusive evidence as unknown. A scrape alone should never upgrade an object to active; stop before expensive or irreversible steps.

  5. Firecrawl has no liveness field. Your application makes that determination in its own domain terms.


Further Reading#