Skip to main content

DeadLinkFinder 🔗🔍

pre-commit SARIF v2.1.0 Python 3.12+ License: MIT Tests Zero Dependencies

DeadLinkFinder is a zero-dependency Markdown integrity checker for local links, images, heading anchors, and optional external URLs.
Prevent broken links, missing image assets, and dead #anchor fragments in your documentation before they reach production.

DeadLinkFinder Demo

$ deadlinkfinder docs/

🔗 DeadLinkFinder v0.2.1 — Verifying documentation integrity...
[!] DLF-001  ERROR    docs/getting-started.md:28
    Target not found: '../guides/setup.md'
    Suggestion: Did you mean '../guides/installation.md'?

[!] DLF-002  WARNING  docs/api-reference.md:104
    Heading anchor not found: '#authentication-keys'

[✗] 2 issues detected across 14 scanned files (exit 1).
    Emitted SARIF report to 'deadlinks.sarif' (OASIS v2.1.0 compliant).

🌟 Architecture & Capabilities

Core Engine (100% Offline, Zero Network)

  • Zero External Dependencies: Built strictly using the Python Standard Library (re, pathlib, argparse, difflib, json, urllib). Requires no third-party package installation (dependencies = []).
  • GitHub-style Anchor Engine: Generates GitHub-compatible heading anchors for common GFM Markdown headings, including punctuation, Unicode text, emojis, and duplicate headings (#section, #section-1). The anchor behavior is covered by compatibility fixtures for common GitHub Markdown cases.
  • Local Asset Verification: Distinguishes between document pages and image assets (.png, .jpg, .svg), reporting missing assets with dedicated rule IDs.
  • Cross-File Anchor Verification: Validates complex references like [API Reference](docs/api.md#authentication) by inspecting the target file's heading tree.
  • Code Block Isolation: Automatically ignores fenced code blocks (```...```) and inline backtick spans so tutorial examples never trigger false alarms.
  • Fuzzy "Did You Mean?" Suggestions: Suggests closest matching file paths when a relative link has a typo or moved location.
  • Deterministic Exit Codes: 0 (clean), 1 (broken references found), 2 (CLI error or target not found).

Optional Network Mode

  • External URL Validation: When explicitly enabled via --check-external, validates remote http:// and https:// links.
  • Timeout Management: Configurable network timeout thresholds (--timeout 5.0) with isolated timeout error reporting (DLF-007).
  • Offline By Default: Fast, safe local execution by default without unexpected network calls.

🔍 Validation Rules

Rule IDs are permanent and deterministic for stable CI/CD and SARIF triage:

Rule ID Name Default Level Description
DLF-001 Broken Local File Link error Referenced relative file path does not exist on disk
DLF-002 Missing Anchor Slug warning Target #heading-anchor not found in target Markdown document
DLF-003 Broken External URL warning Remote HTTP/HTTPS URL returned an error status ($\ge 400$)
DLF-004 Missing Local Image error Referenced graphic or screenshot asset does not exist on disk
DLF-005 Invalid Markdown Target error Target destination is empty or contains malformed syntax
DLF-006 Skipped Code Block Reference note Informational rule indicating ignored code snippet URLs
DLF-007 External URL Timeout warning Remote URL did not respond within configured timeout

🚀 Quick Start

Installation

Recommended via pipx for isolated CLI usage:

pipx install deadlinkfinder

Or install via pip:

pip install .

Or run directly from source without installation:

git clone https://github.com/umutgungorr/deadlinkfinder.git
cd deadlinkfinder
python -m deadlinkfinder .

🛠️ Usage & Examples

1. Scan Local Documentation (Core Offline Mode)

Scans local Markdown files quickly with no runtime dependencies. On standard documentation repositories, local scans typically complete in milliseconds:

deadlinkfinder

2. Export SARIF for GitHub Code Scanning

SARIF findings include stable partial fingerprints (partialFingerprints.primaryLocationLineHash) to prevent duplicate Code Scanning alerts across repeated workflow runs:

deadlinkfinder --format sarif -o results.sarif

3. Machine-Parseable JSON Output

deadlinkfinder --format json -o deadlinks.json

4. Optional External URL Checking

deadlinkfinder --check-external --timeout 5.0

🤖 CI/CD Integration (GitHub Actions)

Use this when documentation errors should prevent pull requests from merging:

name: Documentation Integrity

on: [push, pull_request]

permissions:
  contents: read
  security-events: write

jobs:
  deadlinkfinder:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: '3.12'

      - name: Verify Documentation Links
        run: |
          python -m deadlinkfinder --format sarif -o results.sarif .

      - name: Upload SARIF to GitHub Code Scanning
        uses: github/codeql-action/upload-sarif@v3
        if: always()
        with:
          sarif_file: results.sarif

Option B: Advisory / Reporting-Only Mode

Use continue-on-error: true if you only want alerts reported in the GitHub Security tab without blocking PR merges:

      - name: Verify Documentation Links (Advisory)
        run: |
          python -m deadlinkfinder --format sarif -o results.sarif .
        continue-on-error: true

Note: Remove continue-on-error: true if broken documentation should fail the workflow.


📋 Scope & Known Limitations

Supported

  • Standard Markdown links: [Text](path/to/doc.md)
  • Relative file references across directories: ../guide.md
  • Relative image links: ![Alt Text](./assets/diagram.png)
  • Same-file heading anchors: [Jump](#quick-start)
  • Cross-file heading anchors: [Guide](docs/setup.md#installation)
  • ATX headings with custom punctuation, emojis, and duplicate suffixes (-1, -2)
  • Fenced code block isolation (```...``` and ~~~...~~~)
  • Inline backtick span isolation ( ... )

Known Limitations

  • Complex inline raw HTML tags (<a href="...">) receive best-effort regex parsing.
  • Reference-style links ([text][ref]) with distant definitions have limited support.
  • JavaScript-rendered client-side Single Page Application (SPA) links are not executed.
  • External URL checks require network access and are skipped by default.

🧪 Test Coverage

DeadLinkFinder is verified against a comprehensive fixture suite:

  • Unicode and multi-language heading slugs
  • Emoji-prefixed headings (## 🚀 Quick Start $\rightarrow$ #quick-start)
  • Duplicate heading counters (#section, #section-1)
  • Missing image asset detection (DLF-004)
  • Cross-file anchor resolution
  • Mixed POSIX and Windows backslash paths
  • Empty and malformed Markdown targets (DLF-005)
  • SARIF v2.1.0 schema validity and partial fingerprints

Run tests locally:

python -m pytest tests contract_tests -v

📄 License

MIT License. See LICENSE for details.

Release files for deadlinkfinder 0.2.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for deadlinkfinder 0.2.1
File Size Uploaded
deadlinkfinder-0.2.1.tar.gz 646.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for deadlinkfinder 0.2.1
File Interpreter ABI Platform
deadlinkfinder-0.2.1-py3-none-any.whl Python 3 none any Details

Total release size: 663.1 kB

Release files / deadlinkfinder-0.2.1.tar.gz

Download URL deadlinkfinder-0.2.1.tar.gz
Size 646.3 kB
Tags Source
SHA-256 checksum
How to use checksums
f3998f8ebcf3ed8ebd042e4591b6c82fcf675b571aabe44747cfd2d125f3d9f3
BLAKE2b-256 checksum
How to use checksums
26b4e8f7a71689c956dfb631a874a2e373e2b54bdf9fe64054409ff29641fcf4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.13

Release files / deadlinkfinder-0.2.1-py3-none-any.whl

Download URL deadlinkfinder-0.2.1-py3-none-any.whl
Size 16.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
92a97adcc20d6c4e39427934b4eb119229895677debceb3c00f08620fd9f398f
BLAKE2b-256 checksum
How to use checksums
00c896a71a82627a2fef0799961836698386b65fa24d5d626bba75c51a8cdf92
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.13

Release history Release notifications | RSS feed

This release

0.2.1 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page