Schedule icon
Download icon
Script icon
Docker icon
If icon
SlackIncomingWebhook icon
Fail icon
Log icon

Check Markdown Files for Dead Links

Automatically extract and check all HTTP/HTTPS links in a Markdown file. Get Slack alerts for dead links and handle timeouts, redirects, and retries.

Categories
Infrastructure

Dead links in READMEs and documentation erode user trust and cause frustration. This blueprint automates link checking by downloading a Markdown file, extracting all URLs, and testing them for accessibility. It handles rate limits, redirects, and server rejections elegantly, alerting you in Slack when links rot.

How it works

  1. download (io.kestra.plugin.core.http.Download) fetches the raw Markdown file to Kestra's internal storage.
  2. check_links (io.kestra.plugin.scripts.python.Script) runs a slim Python script in a Docker container. It deduplicates links, skips local addresses, and uses HEAD requests to verify URLs quickly, falling back to GET for servers that block HEAD.
  3. evaluate (io.kestra.plugin.core.flow.If) branches based on the results. If dead links are found, it posts a detailed JSON payload to Slack and conditionally fails the execution. If all links pass, it logs a success message.
  4. The errors block acts as a safety net, sending a Slack alert if the flow itself fails to execute.

What you get

  • Automated, repeatable link hygiene for your documentation.
  • Detailed Slack notifications listing exactly which links died and why.
  • Graceful handling of common web scraping pitfalls like 405 Method Not Allowed or 403 Forbidden on HEAD requests.

Who it's for

  • DevRel and documentation teams managing large repositories.
  • Open-source maintainers who want to ensure their READMEs stay current.
  • Infrastructure engineers enforcing documentation policies.

Why orchestrate this with Kestra

Instead of relying on a fragile local script or a CI job that hides results in logs, orchestrating this with Kestra gives you scheduled execution, automatic Slack alerts, and a clear audit trail. You get visibility into how many links were checked and exactly what failed, right in the Kestra UI and your team's Slack channel.

Prerequisites

  • A local docker run command or Docker service for Kestra to run the Python image.
  • A Slack incoming webhook configured for your workspace.

Secrets

  • SLACK_WEBHOOK_URL: The Slack webhook URL used to send notifications for dead links and flow failures. Note: Secrets are passed as environment variables prefixed with SECRET_ and base64-encoded (example: SECRET_SLACK_WEBHOOK_URL=<base64 of the url>).

Inputs

  • markdown_url: The URL of the Markdown file to check.
  • timeout_seconds: The timeout for each HTTP request.
  • fail_on_dead_links: Whether to fail the Kestra execution if any dead links are found.

Outputs

  • {{ outputs.download.uri }}: The internal storage path of the downloaded Markdown file.
  • {{ outputs.check_links.vars.dead_count }}: The total number of dead links found.
  • {{ outputs.check_links.vars.dead_links }}: A JSON array containing the dead URLs and their error messages.

Quick start

  1. Store your Slack webhook URL in the SLACK_WEBHOOK_URL secret.
  2. Upload this blueprint and run it manually against a raw README URL.
  3. Enable the weekly_schedule trigger to monitor your links automatically.

How to extend

  • Add an input for a list of URLs and use a ForEach task to check multiple documentation files in parallel.
  • Store the results in a database like PostgreSQL or BigQuery for long-term tracking of documentation health.
  • Instead of just checking URLs, extend the Python script to validate anchor links within the same repository.

Pitfalls

  • Disabled schedule: The schedule is disabled by default. You must set disabled: false to run it automatically.
  • Bot-blocking sites: Some websites block automated requests entirely. The script uses a standard User-Agent, but aggressive CDNs might still return a 403.
  • Rate limits: Checking a page with hundreds of links to the same domain might trigger rate limits (429). The script includes simple retries, but a large file might require a longer timeout or a delay between requests.
  • Redirects: The urllib library handles standard redirects automatically, but complex JavaScript redirects will not be followed.
  • Secret setup: Ensure the Slack webhook secret is created correctly.
  • Expression syntax: Be careful when editing Pebble expressions; ensure variables like outputs.check_links.vars.dead_count exactly match the emitted outputs.

Links

See How

New to Kestra?

Use blueprints to kickstart your first workflows.