Guide
By Axel Antas-Bergkvist Published May 4, 2026 Updated May 25, 2026

How to bulk-fix broken internal links across WordPress

Internal links go bad in a few predictable ways. You changed domain (oldname.comnewname.com) and a sweep two years ago caught most of them but not the ones in old posts. You restructured your URLs (/blog/post-name/articles/post-name) and the redirects work, but every internal link is now a wasted 301. You deleted a category page or merged two posts, and now thirty old posts point to a 404. Or you linked to something on someone else’s site that has since vanished.

Plugins like Broken Link Checker can find these. They’re worse at fixing them at scale — you still end up clicking through each result, editing one post at a time in the Block Editor. For a few links, fine. For a few hundred, it’s the same wall every bulk WordPress job hits.

The fix is the same as every other bulk job: pull your posts down to a folder of markdown, do the find-and-replace at the folder level, preview, push back. This is one of the cleanest applications of the bulk edit pattern because the operation is mechanical — strings in, strings out — so the risk of an AI getting clever is low.

Step 1: get the whole site into a folder

Connect Specter with your site URL, username, and an Application Password. Pick a folder. The first sync pulls every post and page down as .md files, each with frontmatter at the top and the post body as plain markdown underneath. Links in the body are standard [text](url) syntax. Links in shortcodes or HTML blocks stay as HTML.

If you haven’t connected yet, connect Specter to WordPress walks through the setup.

You’ve got two options depending on what you know.

If you know the patterns (you changed domain, you restructured a URL prefix, you deleted a specific post), skip straight to the swap. You don’t need to find anything — you know what to replace.

If you don’t know what’s broken, scan the folder. A short script pulls every URL out of every file, deduplicates, and checks each one’s HTTP status:

grep -rohE 'https?://[^)"]+' . | sort -u > all-links.txt

Then check status codes in batches with httpx or a quick Python script. You end up with a list of bad URLs and the canonical fixes — input for step 3. A script is faster and more accurate than an AI for “is this URL alive?” — save the AI for the next step.

Step 3: do the swap

For a clean find-and-replace — oldname.comnewname.com everywhere — a script is the right tool:

find . -name "*.md" -exec sed -i '' \
  's|https://oldname.com|https://newname.com|g' {} +

(macOS sed; Linux drops the empty ''.)

For something with more nuance — say you deleted a post and want to retarget every link to the closest-matching survivor — an AI fits better:

For every .md file in this folder, find any link to
https://example.com/old-post-slug and replace it with a
link to the most topically relevant surviving post in the
folder. Use the post title and first paragraph to decide
relevance. Print the file, the old URL, the new URL, and
a one-line reason for each change.

The “print the reason” line is important. It gives you something to audit before you push, instead of just trusting that the swap was sensible. If the AI’s logic looks off on a row, you can override it before the sync.

For domain or path restructures with a mapping file (a few hundred rows), a script is again the cleanest tool. Either approach works on the same folder — pick the one that matches the messiness of the job.

Step 4: preview the diff, then push

Specter’s dry-run preview lays out every post that would be updated and shows the old and new link in context. For a link-fix job, this is the only audit you need: scroll the list, spot-check a dozen rows, look for any updates that don’t make sense.

If everything looks right, sync. Specter batches the updates over the REST API in the background — long sweeps don’t time out the way ad-hoc API scripts will.

If a teammate edited a post in wp-admin between your sync down and your push back, Specter flags it as a conflict and asks which version wins. That matters more on a link-fix sweep than most other jobs because the conflict could be that someone fixed the same link a different way. The conflict prompt is what stops you from quietly undoing their work.

This workflow handles internal links cleanly because you control where they should point. External broken links are trickier. The AI can sometimes find a replacement (the same article on the Wayback Machine, or a newer version on the same author’s site), but more often the right move is to remove the link and edit the sentence around it. Either way, the folder is the surface you do that on.

Where this fits

Link cleanup is perpetually overdue because the WordPress admin makes it tedious. With the bulk-edit setup already in place and your Application Password minted, it becomes a half-hour job instead of a quarter-long project. Run it after every URL change. Run it when you delete a post.

Buy Specter Pro — $99/year Browse all WordPress guides