Siftsmith
← All tools

Find recently updated pages on a website

Most company websites publish a sitemap that lists every page with the date it last changed. Read it and you can see what a company touched in the last month (new integrations, a changelog entry, a pricing edit) without setting up a monitor first. This page shows how to do that by hand, which dates to distrust, and how to do it for a list of companies in one run.

Why the sitemap is the place to look

A sitemap is an XML file, usually at /sitemap.xml and named in /robots.txt, that a site publishes for search engines. Each page gets a <loc> (its URL) and often a <lastmod> (when the site says it last changed). Because the dates are already there, you get the last few months of history on the first look. A page monitor only sees changes made after you add a page to it.

Grouped by section, the dates say what a company is working on:

What it can’t tell you: what changed on the page, or whether the page is new or edited. The date says only that the site considers the page changed.

Read a sitemap by hand

1. Find the sitemap

Open https://domain/robots.txt and look for Sitemap: lines. If there are none, try /sitemap.xml and /sitemap_index.xml. If the file you open is a <sitemapindex>, it lists more sitemap files rather than pages; open each <loc> inside it (sitemap-blog.xml, sitemap-product-pages.xml and so on).

2. List the most recently changed pages

For a single sitemap file this prints every dated page, newest first:

curl -sL https://linear.app/sitemap.xml | tr -d '\n' | awk '{gsub(/<url>/,"\n")}1' \
  | sed -n 's:.*<loc>\(.*\)</loc>.*<lastmod>\(.*\)</lastmod>.*:\2 \1:p' \
  | sort -r | head

On 27 September 2026 it returned:

2026-09-26T12:50:49Z https://linear.app/integrations/teamretro
2026-09-25T20:22:07Z https://linear.app/docs/billing-and-plans
2026-09-25T15:00:20Z https://linear.app/docs/diffs-integrations
2026-09-25T07:59:41Z https://linear.app/changelog/2026-09-24-new-controls-for-linear-coding-agent
2026-09-25T01:42:26Z https://linear.app/docs/jira
2026-09-24T22:36:54Z https://linear.app/enablement/guides/coding-sessions
2026-09-24T22:36:54Z https://linear.app/enablement/guide/coding-sessions
2026-09-24T22:36:54Z https://linear.app/docs/coding-sessions
2026-09-24T16:10:54Z https://linear.app/docs/projects
2026-09-24T15:57:36Z https://linear.app/docs/project-status

A new integration page, a changelog entry and a batch of docs, all in the last three days. The command assumes <lastmod> comes after <loc> inside each <url>, which is the usual order. If you don’t use a terminal, open the sitemap in a browser and search the page for this month’s date, e.g. 2026-09.

3. Count changes in the last 30 days

# GNU date (Linux); on macOS replace the date part with: date -u -v-30d +%FT%TZ
curl -sL https://linear.app/sitemap.xml | tr -d '\n' | awk '{gsub(/<url>/,"\n")}1' \
  | sed -n 's:.*<lastmod>\(.*\)</lastmod>.*:\1:p' \
  | awk -v d="$(date -u -d '30 days ago' +%FT%TZ)" '$0 >= d' | wc -l

That compares dates as text, which works for UTC dates ending in Z and for date-only values; a date written with an offset such as +02:00 can be off by a few hours. For linear.app it printed 97. Hold on to that number; the next section is about why it’s too high.

Which dates to distrust

A <lastmod> is whatever the site’s software writes. Plenty of sites write dates that have nothing to do with anyone editing a page. Before you trust a count, run this on the same file. It prints the most common exact timestamps. For vercel.com on 27 September 2026:

curl -sL https://vercel.com/sitemap.xml | tr -d '\n' | awk '{gsub(/<url>/,"\n")}1' \
  | sed -n 's:.*<lastmod>\(.*\)</lastmod>.*:\1:p' | sort | uniq -c | sort -rn | head -4
    831 2026-06-17T09:43:59.816Z
    809 2026-08-18T06:10:12.418Z
    539 2026-09-27T11:09:45.522Z
    434 2026-08-29T03:11:19.144Z

809 pages don’t get edited on the same millisecond. Those are jobs that rewrote the dates in bulk, and the third line was stamped the same morning we ran the command. Count vercel.com’s last 30 days with the command from step 3 and you get 3,827 of its 7,378 dated URLs, nearly all of them noise. The patterns to look for:

Filtering this by hand for one site is a few minutes of sort | uniq -c. For a list of 50 companies, each with several sitemap files, it’s an afternoon.

Check a list of companies in one run

Launch Signals reads each company’s sitemap (via robots.txt, following sitemap indexes and gzipped files), throws out the dates that fail the checks above, and returns one row per domain with counts for the last 7, 30 and 90 days split by section. Put domains into Domains on the Apify Store page, or send JSON through the API:

{
  "domains": ["linear.app", "intercom.com", "vercel.com",
              "figma.com", "stripe.com"]
}

What that run returned (27 September 2026)

Inputstatuslast7dlast30dlast90dlaunchScoreCharged
linear.appok226816682$0.03
intercom.comok6619839245$0.03
vercel.comlastmod_unreliableno counts: 94% of the last 90 days’ dates failed the filterfree
figma.compartial_coverageno counts: 20 of 38 sitemap files read before the 50,000-URL capfree
stripe.comno_lastmodno counts: the sitemap has no datesfree

The run cost $0.06: two domains at $0.03, the other three free. The linear.app row, trimmed:

{
  "input": "linear.app",
  "status": "ok",
  "launchScore": 82,
  "changes": { "last7d": 22, "last30d": 68, "last90d": 166 },
  "bySection": {
    "changelog":    { "urls": 255, "dated": 162, "last7d": 1,  "last30d": 3,  "last90d": 9 },
    "integrations": { "urls": 325, "dated": 268, "last7d": 3,  "last30d": 16, "last90d": 54 },
    "customers":    { "urls": 43,  "dated": 28,  "last7d": 0,  "last30d": 2,  "last90d": 6 },
    "docs":         { "urls": 203, "dated": 160, "last7d": 17, "last30d": 42, "last90d": 77 },
    "pricing":      { "urls": 1,   "dated": 0,   "last7d": 0,  "last30d": 0,  "last90d": 0 }
  },
  "latestChangeAt": "2026-09-26T12:50:49.000Z",
  "notableUrls": [
    { "url": "https://linear.app/integrations/teamretro",
      "section": "integrations", "lastmod": "2026-09-26T12:50:49.000Z" },
    { "url": "https://linear.app/changelog/2026-09-24-new-controls-for-linear-coding-agent",
      "section": "changelog", "lastmod": "2026-09-25T07:59:41.000Z" }
  ],
  "pitchReasons": [
    "3 changelog/release pages updated in the last 30 days (latest: /changelog/2026-09-24-new-controls-for-linear-coding-agent): shipping actively; reference a recent release in outreach",
    "16 integration pages updated in the last 30 days (e.g. /integrations/teamretro): expanding their ecosystem; partnership or integration pitch",
    ...
  ],
  "reason": "Counts exclude 61 of 227 URLs dated in the last 90 days as machine restamps (1 same-timestamp batch in the last 90 days, largest 10 URLs at 2026-07-23T15:28:23.000Z (over 265s); 2 one-by-one sweeps in the last 90 days, largest 23 blog pages from 2026-07-23T15:02:07.000Z over 80 min)."
}

What to take from it:

How the filter decides

Build-date stamp60% or more of dated pages share one day in the last 90 days (50% if that day is within 2 days of the check or matches the sitemap file’s own Last-Modified): the domain is lastmod_unreliable
Same-timestamp batch5 or more URLs on the same second, or a chain of 10 or more each within 60 seconds of the last: excluded
Bulk-update hourOne clock hour holding at least 20 stamped URLs, or 3% of the site’s dated pages if that’s more (the bar tops out at 100): excluded
Stamped sitemap fileA file with 10 or more dated URLs, 70% of them on one recent day: that file is excluded
Restamped section5 or more dated pages in a section, 80% on one recent day: that section is excluded
Rolling section20 or more dated pages, 80% “changed” in the last 7 days: excluded (the same test on the whole site makes it lastmod_unreliable)
Sweep8 or more pages of one section within 60 minutes: excluded
EchoesCategory, tag, author and index pages sharing a post’s second count as one change, and never on their own
Too little leftOver 90% of the last 90 days’ dates excluded, or fewer than 5 trustworthy changes: no counts, free

The filter errs toward under-counting. A real launch that touched 200 pages in one deploy is excluded as a batch, and so is a genuine edit to 8 pages of one section inside an hour. The same page in several languages counts once.

Crawling: it identifies itself as SiftsmithBot/0.1 (+https://siftsmith.com), obeys robots.txt, and fetches only robots.txt and sitemap files, never the pages themselves.

Other ways to do it

ToolWhat it isPrice (official page)
VisualpingPage-change monitor: checks the pages you add on a schedule and shows what changed on themFree for 5 pages checked hourly; Personal $14/month for 10 pages ($10/month billed yearly); Business $140/month for 200 pages ($100/month billed yearly)
Sitemap URL Extractor (an Apify Actor by another developer)Lists every URL in a site’s sitemaps with its lastmod, optionally only those changed since a date$0.50 per 1,000 URLs on Apify’s free plan, from $0.20 per 1,000 on higher tiers
Launch SignalsFiltered 7/30/90-day counts by section for a list of domains$0.03 per domain with a trustworthy result; other rows free; no subscription

They answer different questions. A monitor like Visualping shows you the actual text or visual change on a page, which a sitemap never will, but only on pages you chose in advance and only from the day you added them. A raw sitemap export gives you every URL and date, which is the right tool for SEO work, and its own page says the lastmod “is reported as the sitemap writes it; it is not independently verified”, so the checks above are up to you. Launch Signals gives one filtered summary per company across all sections, with history from the first run, and nothing about what changed inside a page.

Prices checked 27 September 2026 on Visualping pricing and the Sitemap URL Extractor Store page.

What it costs

Analyzed domain$0.03 ($30 per 1,000), no subscription

A domain is charged only when its row comes back status: "ok". That takes all of these:

Every other row is free: lastmod_unreliable, no_lastmod, stale_sitemap, too_few_changes, no_notable_changes, partial_coverage, no_sitemap, sitemap_fetch_failed, blocked_by_robots, redirected, sitemap_empty, nxdomain, unreachable, not_public, invalid input and errors. Free rows have changes: null, never zeros. Duplicates are free too: https://www.linear.app/pricing and linear.app are one domain, and two inputs that read the same sitemaps (notion.so and notion.com) are one site, charged once.

Set a maximum total charge for the run and you’re never charged past it. Once it’s reached, every input left over still gets a row with skipped: true, uncharged.

FAQ

Can I see when a company last changed its pricing page?

Only if the pricing page is in the sitemap with a <lastmod>. Search the sitemap for pricing; if it’s there with a date, that’s the site’s own claim of the last change. When a pricing change turns up in a run, it gets its own pitch reason. If you need to know what changed in the prices, use a page monitor on that one page.

Does a recent lastmod mean the page is new?

No. It means the site considers the page changed. notableUrls are recently changed pages, not necessarily new ones.

What does it cost to check 200 companies?

At most $6. Sites with no dates, unreliable dates or nothing notable in the last 30 days are free, so it’s usually less; in the five-domain run above, three of five were free.

Can I run it every week?

Yes. Schedule it on Apify, or call it from Clay, Make, Zapier or the API. Using our tools in Clay has the steps, and the MCP page shows how to give it to an AI agent.

Check your list on the Apify Store →

Fields, statuses and pricing in one place: the Launch Signals product page.