Skip to content

Link Checking Tools — Complete Guide

DodaTech Updated 2026-06-28 4 min read

Link checking tools validate internal and external links in documentation, preventing broken links that frustrate readers. Learn how to configure HTMLProofer, lychee, and integrate link checking into CI/CD.

What You'll Learn

You will learn how to set up automated link checking, the differences between tools, and best practices for link maintenance in documentation.

Why It Matters

Broken links erode reader trust and waste time. Every broken link in documentation sends users to a dead end. Automated link checking catches these before they reach production.

Real-World Use

DodaTech runs HTMLProofer on every build, checking all internal links and a subset of external links. A weekly scheduled workflow checks all external links.

flowchart LR
  A[Build Documentation] --> B[Link Checker]
  B --> C[Internal Links]
  B --> D[External Links]
  B --> E[Image References]
  C --> F{All Valid?}
  D --> F
  E --> F
  F -->|Yes| G[Deploy]
  F -->|No| H[Report Errors]
  A:::current
  classDef current fill:#f90,color:#fff,stroke:#333,stroke-width:2px

Tool Comparison

Feature HTMLProofer lychee broken-link-checker
Language Ruby Rust JavaScript
Performance Moderate Fast Moderate
Internal links Yes Yes Yes
External links Yes Yes Yes
Image checking Yes Yes No
Custom ignore Yes Yes Yes
CI integration Yes Yes Yes

HTMLProofer Configuration

# Install
gem install html-proofer

# Run against built documentation
htmlproofer public/ \
  --check-html \
  --check-img-http \
  --disable-external \
  --allow-hash-href \
  --alt-ignore "icon,logo" \
  --url-ignore "/fonts.googleapis.com/"

Expected output:

Running 29 checks on 142 files...
HTML-Proofer finished successfully.

lychee Configuration

# lychee.toml
max_retries = 3
timeout = 30
retry_wait_time = 5
include_verbatim = true

[exclude]
  paths = ["node_modules", "public"]
  URLs = ["https://linkedin.com", "http://localhost"]
# Run lychee
lychee public/

Expected output:

🔍 142 links checked (140 OK, 2 errors, 0 excluded)
📝 Found 2 errors:
  - public/index.html → https://example.com/docs/ 404 Not Found

CI Integration

# .github/workflows/links.yml
name: Link Check
on:
  pull_request:
    paths:
      - 'content/**'
  schedule:
    - cron: "0 6 * * 1"  # Weekly external check
jobs:
  check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: peaceiris/actions-hugo@v2
      - run: hugo --gc --minify
      - name: Internal link check
        run: htmlproofer public/ --disable-external --check-html
      - name: External link check (weekly)
        if: github.event_name == 'schedule'
        run: htmlproofer public/ --check-html

Common Mistakes

External link checking is slow and unreliable. Run internal checks on every build and external checks on a schedule.

2. Not Checking Image References

Broken images look unprofessional. Configure your link checker to validate image sources.

3. Ignoring Redirect Chains

A link that redirects multiple times is not ideal. Check for excessive redirects and update to final URLs.

4. Not Running Against the Built Output

Link checkers must run against generated HTML, not Markdown source. Relative links resolve differently after building.

5. No Failure Notification

When link checking fails, someone must be notified. Configure CI notifications for link check failures.

Practice Questions

1. Why should internal and external link checking run on different schedules?

Internal checks are fast and reliable (run on every build). External checks are slow and may fail due to external site issues.

2. What does the --disable-external flag do in HTMLProofer?

It skips external link validation and only checks internal links, images, and HTML structure.

3. Why should link checkers run against built HTML, not Markdown source?

Relative links, shortcodes, and includes resolve differently after the SSG processes them.

4. How do you handle external sites that block automated link checkers?

Add them to an ignore list. These sites may block crawlers regardless of the checker used.

5. Challenge: Set up HTMLProofer to check all internal links on a Hugo documentation site. Create a second workflow that checks external links once per week. Configure notifications for failures.

FAQ

Can link checkers validate JavaScript-generated links?

No. Link checkers analyze static HTML. For JS-generated content, use a headless browser.

What is a redirect chain and why does it matter?

A redirect chain happens when URL A redirects to B which redirects to C. Each redirect adds latency. Update links to point directly to the final URL.

How do I handle anchor links (fragments) to page sections?

Link checkers can validate that fragment targets exist in the HTML output.

Should I check links in draft pages?

Only if drafts are included in the build. Use --buildDrafts to include them.

What is the best link checker for large documentation sites?

lychee (Rust) is fastest. HTMLProofer (Ruby) has the most features.

Mini Project

Set up link checking for a documentation site. Configure HTMLProofer for internal checks on every PR and external checks on a weekly schedule. Add an ignore list for known problematic external sites. Fix all broken internal links.

What's Next

After link checking, explore Image Editing tools for creating and optimizing documentation screenshots and diagrams.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro