johnhenry / craft-link-audit
Finds broken links in your Craft content, checks each unique address once, and shows which entries to fix.
Package info
github.com/john-henry/craft-link-audit
Type:craft-plugin
pkg:composer/johnhenry/craft-link-audit
Requires
- php: ^8.2
- craftcms/cms: ^5.6
- johnhenry/craft-ip-guard: ^1.3
Requires (Dev)
- craftcms/commerce: ^5.0
- craftcms/ecs: dev-main
- craftcms/html-field: ^1.0 || ^2.0 || ^3.0
- craftcms/phpstan: dev-main
- phpstan/phpstan: ^2.2
- verbb/hyper: ^2.0 || ^3.0
- verbb/navigation: ^3.0 || ^4.0
Suggests
- craftcms/ckeditor: Links in CKEditor content are read from the stored HTML, nested entries and all
- verbb/hyper: Hyper field links are read the same way native Link field values are
- verbb/navigation: Custom URLs on navigation nodes are scanned alongside your content
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-09-28 09:29:48 UTC
README
Link Audit for Craft CMS
A broken link checker for Craft CMS 5. Links break on other people's sites and nobody tells you, so it goes through your stored content, checks each unique address once, and shows you the exact entries carrying the ones that are broken.
The thinking behind it
Most link checkers go page by page: load a page, check its links, move on to the next. That falls over on a site of any size. If your footer links to a supplier, that supplier is on every page you have, and a page-by-page checker will ask them about it thousands of times in one run. Sooner or later they block you for it, everything they host turns up as broken, and the report stops being believed.
Link Audit keeps one record per unique address instead. The footer link is checked once, however many pages carry it, and the plugin remembers every entry, field and site it appears in, so when it does break you can see where to go and fix it.
Verdicts are kept for a while rather than thrown away. A working link is trusted for 30 days before it is asked again. A broken one is rechecked the next day, so a fix shows up quickly. The first scan does the heavy lifting; the ones after it only look at what has gone stale.
It also knows the difference between a broken link and a host that will not talk to robots. LinkedIn, Cloudflare and their kind refuse automated requests no matter how healthy the link is, so those answers go on their own screen, marked Unverifiable, and are never counted as broken. A link that gives no answer at all is only called broken after it has failed a few times in a row, because one bad afternoon on somebody else's server is not news.
What it reads
Stored field values, not rendered pages:
- Rich text (CKEditor and Redactor), including links inside nested entries
- Native Link fields and URL fields
- Hyper fields
- Matrix and content blocks, as deep as they go
- Navigation nodes, if you have verbb/navigation installed
- Image and iframe sources in rich text, if you turn them on
Because it reads stored values, it sees links on entries that have no public URL, and it can tell you which field a link came from. Internal links are resolved against your own elements and routes rather than fetched over HTTP, and whatever those cannot answer for is asked for over HTTP, so a redirect rule in Retour or in your server config counts as the redirect it is rather than as a broken link.
There is a rendered crawl mode as well, for links hard-coded into templates. It is off by default, because fetching every page is the expensive way to do it.
Documentation
Full documentation is at johnhenry.ie/plugins/link-audit/docs.
Requirements
- Craft CMS 5.6 or later
- PHP 8.2 or later
Accessibility
How accessible the plugin is, what's been checked, and how to report a problem are all in the accessibility statement.
Support
Need a hand? Open an issue on the GitHub Issues page.
License
This plugin is free to use under the MIT License.