Skip to main content

DeadLinkFinder 🔗🔍

PyPI version PyPI Downloads 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 deadlinkfinder

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)
  • reStructuredText hyperlinks: `Text <path/to/doc.rst>`_ and targets (.. _target: url)
  • Sphinx / Docutils roles: :doc:\...`, :ref:`...`, :download:`...``
  • reStructuredText images and figures: .. image:: path and .. figure:: path
  • Relative file references across directories: ../guide.md, ../guide.rst
  • Relative image links: ![Alt Text](./assets/diagram.png)
  • Same-file heading anchors: [Jump](#quick-start), `Jump <#quick-start>`_
  • Cross-file heading anchors: [Guide](docs/setup.md#installation), `Guide <docs/setup.rst#installation>`_
  • ATX headings with custom punctuation, emojis, and duplicate suffixes (-1, -2)
  • reStructuredText section underlines (=, -, ~, etc.) and explicit targets (.. _name:)
  • Fenced code block isolation (```...``` and ~~~...~~~)
  • reStructuredText code-block and literal directive isolation (.. code-block::, ::)
  • Inline backtick and literal span isolation ( ... and ... )

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

Project case study

DeadLinkFinder is an open-source project by Umut Güngör. Read the DeadLinkFinder case study for its validation approach, supported checks, and limitations.

📄 License

MIT License. See LICENSE for details.

Metadata

Release files for deadlinkfinder 0.2.2

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.2
File Size Uploaded Provenance Actions
deadlinkfinder-0.2.2.tar.gz 649.6 kB Without provenance Details for deadlinkfinder-0.2.2.tar.gz

Built distribution (wheel)

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

Total release size: 668.5 kB

Release files / deadlinkfinder-0.2.2.tar.gz

Download URL deadlinkfinder-0.2.2.tar.gz
Size 649.6 kB
Tags Source
SHA-256 checksum
How to use checksums
f1bc4c8bb1074f80fb4e655893775503a7e04997837eb9cd7575804ae55c6348
BLAKE2b-256 checksum
How to use checksums
beb05ddcae1b6a3e3ce2d387f5fbd9e9bf16c2d7ce0cdc9c15dd61453223d1e5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.4 {"installer":{"name":"uv","version":"0.12.4","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

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

Download URL deadlinkfinder-0.2.2-py3-none-any.whl
Size 18.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
ac193d6478eb187f2643dc95a2272d7fd9901b40468b81278a3e300de5dc85db
BLAKE2b-256 checksum
How to use checksums
00a95fd8d8fd593f71ab753136d9390413ab4660fd8e4b52f4bb48c21b49da29
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.4 {"installer":{"name":"uv","version":"0.12.4","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Security for deadlinkfinder 0.2.2

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

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