Statac

Checking links to other sites

Have statac refresh ask other sites whether your links to them still work, and what it asks of a site that sees it in its logs.

statac refresh can ask the sites your pages link to whether each link still works, and statac check then tells you which are broken. This page is for two readers: the author of a site, who turns the check on, and the owner of a site the check asks, who may have found it in their logs. If you are the second, see if Statac asked your site.

Turn it on

check_external_links: true

The check is off until statac.yaml says this. After that, each statac refresh checks the links that are due, as its last step, after the thumbnails and webmentions:

Checking 6 external links on 6 sites.
Checked 6 external links: 3 work, 2 broken, 1 didn't answer. Run `statac check` to see the broken ones.

Commit fetched/links, where refresh records the answers, with the rest of the site, as you do the rest of fetched/.

statac serve never checks links, and neither do statac build and statac check, which never use the network.

The first run on a large site can take up to an hour, since each site is asked one request at a time. After that, a daily refresh asks only a few links.

What is checked

  • Each <a href> and <area href> on the built pages that leads to another site. A link to the site itself, at its url or a host in other_hosts, isn’t checked.
  • Each URL once, however many pages link to it, without its # part.
  • Not images, scripts or anything else written in a src attribute.

Refresh includes drafts and scheduled posts, as it does for thumbnails. Check tells their links only with --drafts.

What counts as broken

A link is broken if the other site answered:

  • 404 Not Found or 410 Gone
  • with a host no name server knows
  • with a certificate that has expired or is for another host

Anything else doesn’t say whether the link works: no answer in time, 401, 403, 429, a 5xx, a page asking the visitor to prove they are a person, or any other failure to connect. Check counts those links, and doesn’t list them.

What check shows

Check gives a broken-external-link warning at each place a broken link is written. Where the other site redirects a link permanently to a page that works, and the redirect changes the scheme to https, the host (beyond a www.) or the path (beyond a final slash), it gives an external-link-moved note with the new URL.

After the list of JavaScript the site carries, and before the counts, check sums up the links:

External links:
  1,234 checked by `statac refresh`, the oldest 40 days ago: 1,100 work, 34 broken, 100 didn't answer.
  5 not checked yet. Run `statac refresh` to check them.
  12 left out by `unchecked_external_links`.

statac build says how old the oldest answer is, with what else was fetched:

Fetched: 1,229 external links checked, the oldest 40 days ago.

How often a link is asked

An answer that worked holds for 30 to 45 days, spread by the URL so a site’s links don’t all fall due at once. Any other answer holds for a week. Refresh asks again about each link whose answer has run out.

If many sites in a row don’t answer at all, refresh stops checking and records nothing for them, since the computer may be offline:

Stopped checking external links: 16 sites in a row didn't answer, so this computer may be offline. Statac recorded nothing for them.

A link that is broken or didn’t answer doesn’t change refresh’s exit code.

Leave a link out

unchecked_external_links:
  - https://example.org/

Refresh never asks about a URL in unchecked_external_links, and check counts its links. The list is read as refuse_webmentions_from is: the scheme, a leading www., capitals in the host and a final slash are ignored. A URL covers every page under it, so https://example.org/ covers the whole host.

The record

statac links 1
https://example.net/	ok	2026-10-06
https://example.org/post-2/	404	2026-10-06

fetched/links starts with the line statac links 1, then has a line for each URL: the URL, the answer and the day it was asked, separated by tabs. The answer is one of:

Answer What the site answered
ok The page, so the link works.
moved <url> A permanent redirect to <url>, which works.
404, 410 Not Found, or Gone.
no-host No name server knows the host.
certificate The host’s certificate has expired or is for another host.
unanswered <why> Nothing that says whether the link works, and why, such as 403 or timeout.

A line for a URL no page links to any more is dropped the next time refresh writes the record.

If Statac asked your site

A request whose user agent reads Statac/<version> (link check; +https://statac.dev/link-check/) comes from Statac, a program people use to build their own websites. The author of a site that links to a page on yours asked Statac to check that the link still works.

  • What it asks: a HEAD request for the page the author linked to, then a GET only if that didn’t work. It reads only the headers, never the page.
  • How often: one request at a time to a site, with a second’s pause between them, and at most eight sites at once. A page that worked isn’t asked about again for at least 30 days. If your site answers 429 or 503 and asks Statac to wait, it waits up to a minute, and leaves the rest of your site’s links for the author’s next refresh if you ask for longer.
  • When: only when the author of a site that links to yours runs statac refresh with the check turned on, from their own computer. Statac doesn’t crawl: it never follows links on your pages, and asks only for pages an author linked to.
  • robots.txt: Statac doesn’t read it. Each request is one person’s own computer checking their own links, once in a while, at their request, which is not the crawling robots.txt is for. Google’s user-triggered fetchers don’t read it for the same reason.
  • A challenge: a page asking the visitor to prove they are a person is recorded as no answer, and never got round.

To turn the check away, refuse requests whose user agent holds both Statac/ and link check. Statac records that as no answer, and doesn’t tell the author the link is broken.

Something unclear or wrong? Open an issue.