Skip to main content

How to Extract Markdown Links and Audit Every URL in a Doc

Pull every inline link, reference link, image, and bare URL out of a Markdown file into a clean CSV so you can audit outbound links, find dead ones, and dedupe.

Published By Li Lei
#markdown #links #seo #documentation #audit

How to Extract Markdown Links and Audit Every URL in a Doc

A long Markdown file hides a surprising number of links. A README, a docs page, a blog post you wrote months ago, all of them carry inline links, image references, footnote-style reference links, and the occasional bare URL someone pasted in a hurry. When you need to migrate that content, check it for SEO, or hand it to another team, you want the links as a flat list you can read, sort, and act on, not buried in prose.

This guide walks through how Markdown links are actually written, how to pull them all into one inventory, and how to use that inventory to audit outbound links and hunt down dead ones. You can do the extraction by hand with a regex, or paste the file into the Markdown Link Extractor and get a CSV in one step.

The four shapes a Markdown link takes

Before you can extract links, you have to know what you are looking for. Markdown links come in four common shapes, and a good audit needs all of them.

Inline links are the everyday kind: [text](url). The text in square brackets is what the reader sees, and the URL in parentheses is where it goes. This is the single most important pattern: the [text](url) form always yields the URL as the content of the parentheses. If you only ever match this one pattern, you will catch the bulk of links in most documents.

Reference links split the two halves apart: [text][ref] somewhere in the body, then [ref]: https://example.com defined later, often at the bottom of the file. People use these to keep long paragraphs readable. The catch is that the definition can appear hundreds of lines away from the usage, so a naive line-by-line scan misses the URL unless it resolves the reference.

Image links look almost identical to inline links but start with a bang: ![alt text](image-url). The alt text matters for accessibility and SEO, so when you inventory images you want both the URL and the alt text in your list.

Bare URLs are the ones nobody wrapped in brackets at all, like a raw https://example.com/page sitting in a sentence. Many Markdown renderers autolink these, so they count as real outbound links even though they have no link text.

A worked example: Markdown in, link list out

Here is a small Markdown file with one of each shape:

See the [setup guide](https://docs.example.com/setup) first.
We track issues in [our tracker][gh].

![Architecture diagram](https://cdn.example.com/arch.png)

Raw link: https://status.example.com

[gh]: https://github.com/example/repo/issues

Extracted into a flat list, that becomes:

kind        text                   url                                              line
inline      setup guide            https://docs.example.com/setup                   1
reference   our tracker            https://github.com/example/repo/issues           2
image       Architecture diagram   https://cdn.example.com/arch.png                 4
bare        (none)                 https://status.example.com                       6

Notice that the reference link on line 2 resolved to the definition on line 7, the image kept its alt text, and the bare URL was caught even without brackets. That four-column shape, kind plus text plus URL plus line number, is exactly what you want for an audit, because it tells you not just where every link points but what kind it is and where to go fix it.

Auditing outbound links and finding dead ones

Once the links are in a list, the audit gets practical. A few things I always check:

  • Outbound versus internal. Sort by domain. Internal links (your own site, relative paths) get handled one way during a migration; outbound links to other sites are the ones most likely to have rotted.
  • HTTP versus HTTPS. Any bare http:// link is worth upgrading. They are easy to spot once the URLs sit in one column.
  • Suspicious hosts. Link shorteners, expired-looking domains, and staging URLs that leaked into published content all jump out when you can scan a single list instead of reading paragraphs.

Extraction itself does not tell you whether a link is alive. It does not make network requests, which is exactly why it is fast and private. What it gives you is the candidate list. To actually find dead links, take the URL column and feed it to a link checker or a small script that issues a HEAD request to each one. The extractor's job is to make sure every link in the document ends up in that column, so nothing slips through the audit because it was hidden inside an image tag or a reference definition.

Deduplicating the URL column

Real documents repeat links. The same "read the docs" URL might appear five times across a long page. For a dead-link audit you do not want to check the same URL five times, so dedupe the URL column down to unique values first. For a content audit, though, the duplicates are the point: if one URL appears twenty times, that is a deliberate internal-link strategy or an accident, and either way you want to know.

So I keep two views. One is the full extraction with line numbers, which I use to go edit specific lines. The other is a deduplicated unique-URL list, which I use to run the actual link check. When the list lives in a CSV, splitting out a single column is trivial with a tool like the CSV column extractor, and deduping is one sort-and-unique pass away.

How I use this in a real workflow

The last time I migrated a documentation set, I had about forty Markdown files and no idea how many external dependencies were buried in them. I ran each file through the extractor, concatenated the CSVs, and ended up with just over six hundred links. Deduped, that collapsed to two hundred and ten unique URLs. I ran those through a checker overnight and found nineteen dead links, most of them pointing at a vendor blog that had restructured its URLs. Without the extraction step I would have read forty files line by line and still missed the reference-style links, because those definitions all sat at the bottom of each file where my eyes glaze over. The whole audit took an afternoon instead of a week.

Putting it together

Extracting Markdown links is a small, sharp task that pays off out of all proportion to its effort. Know the four shapes, pull them into a kind-text-URL-line list, keep one full view and one deduplicated view, and hand the URL column to a checker when you need live validation. If your content lives in HTML instead of Markdown, convert it first with HTML to Markdown and run the same extraction, or extract from the HTML directly. Either way, the goal is the same: every link in the document, visible in one place, ready to audit.


Made by Toolora · Updated 2026-06-13