Every post on this site ends with a References & Further Reading section, and my rule is that every link in there has to actually load. Dead links make a blog look abandoned, and a wrong link is worse than no link. My bots check this before anything goes up for my review, and here’s the simple version you can run yourself.
What you need
- A WordPress Application Password (Users > Profile > Application Passwords) for an account that can edit posts
curlandjqon any Linux box
Keep the credentials in environment variables or a locked-down env file (chmod 600), never in the script.
The script
#!/usr/bin/env bash
# linkcheck.sh - check every link in a WordPress post (read-only)
# usage: ./linkcheck.sh https://example.com 123
SITE="$1"; ID="$2"
UA='Mozilla/5.0 (X11; Linux x86_64) Chrome/120'
curl -s -u "$WP_USER:$WP_APP_PASSWORD" \
"$SITE/index.php?rest_route=/wp/v2/posts/$ID&context=edit" \
| jq -r '.content.raw' \
| grep -oE 'href="https?://[^"]+"' | cut -d'"' -f2 | sort -u \
| while read -r url; do
code=$(curl -s -o /dev/null -L -m 20 -A "$UA" -w '%{http_code}' "$url")
[ "$code" = 200 ] && echo "OK $url" || echo "FAIL $code $url"
done
It pulls the draft’s raw content through the REST API (context=edit works on drafts too), grabs every unique link, follows redirects and prints OK or FAIL with the HTTP status. It’s read-only and never changes the post.
Gotchas I’ve hit
- 403 or 406 doesn’t always mean dead. Some news and vendor sites block anything that doesn’t look like a browser. The browser user-agent fixes most of them. If one still fails, open it in a real browser before you decide.
- Redirects.
-Lfollows them. If a link lands somewhere totally different (like a homepage), swap in the real article URL. - Strip tracking junk. Remove
utm_parameters from links before you publish. Cleaner, and it doesn’t leak where your readers came from. - Use canonical sources. For CVEs I’d rather link NVD or the vendor advisory than a blog that copied them.
Run it on every draft, fix the FAILs, run it again. Two minutes, and your readers never hit a dead end.
Have a blessed day! And Happy Hacking!