A dead link is honest about itself. You click, you get a 404, you move on mildly annoyed. The dangerous ones are the links that still work.
Five years ago someone posted a spreadsheet to r/languagelearning listing around 1700 free language-learning resources. No freemium, no trials, no signup, just things that were actually free. It is still one of the more useful things anyone has put on that subreddit, and it is still an Excel file, which means using it involves a great deal of scrolling.
We rebuilt it as something you can browse and filter. Before publishing, we checked all 1730 links, on the theory that a five-year-old list of URLs is really a five-year-old list of promises. 128 of them were dead. That part we expected. Thirty were worse.
The ones that still worked
Every one of those thirty returned HTTP 200 from a domain that resolved perfectly. Any link checker scoring status codes marks them healthy and moves on. They were not healthy. The domains had lapsed, someone else had bought them, and they were serving something else entirely.
A French course link had become a Polish online casino. A Turkish dictionary was a domain-parking page. A Cantonese pronunciation guide redirected to an Indonesian slot-machine affiliate. A Latin practice site was now a Russian finance blog. A Czech course showed a fake "verifying your browser" message and then sent you to an Italian loan company.
One was stranger than the rest. A university page for teaching Greek to the diaspora still had its real title, its real content and its real domain. Someone had stuffed the page body with Indonesian gambling spam pointing at a redirector. That site had not been sold. It had been broken into, and as far as we can tell it still is.
A reader spotted the first one and told us. That prompted the sweep that turned up the other 29, which is the useful lesson here: one visible symptom of this usually means a category of problem rather than a single bad link.
Why the obvious approach fails
The instinct is to fetch every URL and flag whatever does not return 200. We had exactly that, and it found the 128 dead links and none of the thirty live ones, because from a status code's point of view a hijacked domain and a healthy one are indistinguishable.
So we tried reading the pages and matching on keywords, which failed in a more humiliating way. The first pass flagged NRC, Die Zeit, Catalan TV3 and Lithuanian public radio as pornography. "Anal" sits inside the Croatian "analize" and the Catalan "Canal". "Porn" sits inside the Czech "opornych". Eight flags, eight false positives, every one of them a national news organisation.
Even once that was fixed, matching on page text mostly does not work. A dictionary contains the words it defines. A slang glossary is more or less nothing but trigger words. A news site covers gambling regulation. Flag on body text and you will spend your afternoon deleting good resources.
What survives is narrower. Is the page title itself spam? Does the URL redirect to a known domain broker? Does the page link out to a known spam network? Everything else is a hint rather than evidence.
Then there is the part no text scan reaches at all. Twelve of the thirty were parking pages assembled entirely in JavaScript. The server sends an almost-empty page, and the lander builds itself in the browser afterwards. Fetch it with a script, and nothing looks suspicious, because nothing is there. Those twelve turned up only when we opened all 156 unrecognised domains and read them one at a time.
Then we opened the rest by hand
The automated sweep answers one question: is this link hostile? It does not answer the question a reader actually cares about, which is whether the thing on the other end is any good. A page can return 200, belong to its original owner, contain no spam whatsoever and still be a dead-end SEO farm, a stub with four words on it, or a course that stopped halfway through being written in 2013.
So we went through the catalogue by hand and opened the links ourselves. Anything that had quietly hollowed out came off the list. This is the slow, boring part, and it is the only way we know to catch it, because none of those pages looks wrong to a scanner.
The catalogue has also grown since launch. The 1730 figure was the original spreadsheet; we have been adding resources on top of it, so the numbers on the admin side are larger now than the ones this article started with.
What we can and cannot promise
Every link in the list was fetched. Everything that came back readable was scanned; the 156 domains our tooling could not classify were read individually, and the catalogue has since been reviewed by hand for quality rather than only for safety.
What we cannot promise is that every remaining entry is perfect. A hand review is a judgement call, and ours will not match yours on every row. We also treated YouTube, Reddit and Spotify links as safe from takeover, which is true of the domains and says nothing about whether an individual video still exists. Hosts that were unreachable on the day were left alone, because a timeout is not evidence and deleting good resources on a bad afternoon is its own kind of damage.
It is one snapshot, and the rot did not stop when we finished looking. So the list gets rechecked, and if you find something we missed, tell us. There is now a button for exactly that.
What the list can do now
The first version was a list you could filter. Since then, it has grown into the things a directory needs once people actually use it.
Every resource has its own page, with a screenshot of what you are about to click. Screenshots now cover the catalogue, apart from the links that start an instant file download rather than opening a page, which have a badge telling you so before you click.
You can upvote the resources that helped you, so the useful ones rise instead of sitting wherever the spreadsheet happened to put them. You can save resources to your own list and come back to them. You can share a resource with a direct link. You can leave a comment, and reply to someone else's, which is where the context that never fits in a directory row tends to live: which chapters are worth it, what the audio quality is like, whether it still works.
You can report anything that looks wrong, which is the feature this whole article argues for. A reader caught the first casino before any of our tooling did. Now that path is a button rather than an email.
And you can suggest a resource that is missing. Suggestions land in a review queue rather than straight on the site, for reasons the first half of this article covers in some detail.
If you keep a list of links
The lapsed-and-re-registered case is the one most people miss, and it is the one that matters, because a 404 wastes a click while a hijacked domain takes somebody who trusted your list and hands them to a casino.
Check what pages contain, not merely what they return. Anchor your keyword patterns to word boundaries unless you fancy explaining to Die Zeit why you classified them as pornography. And treat a page that looks empty as interesting rather than fine, because that is what modern spam looks like on the way in.
Then, at some point, open the links yourself. Automation tells you what is hostile. It does not tell you what is worth anyone's time.
The rebuilt list is free, has no signup and carries no ads. Credit and a link to the original spreadsheet sit at the bottom of every page, and the per-contributor credits from the sheet are still there.



