# linkinator: A Fast, Configurable Broken Link Checker for Sites, Docs, and CI

> linkinator is a TypeScript-based crawler and link validator that works on live sites, local files, and markdown. It offers a CLI, a library API, Docker images, and strict checking modes for fragments, CSS, redirects, and HTTPS requirements.

**JustinBeckwith/linkinator** — Broken link checker that crawls websites and validates links. Find broken links, dead links, and invalid URLs in websites, documentation, and local files. Perfect for SEO audits and CI/CD.

- Repository: https://github.com/JustinBeckwith/linkinator
- Stars: 1,276 · Forks: 111
- Language: TypeScript
- License: MIT
- Published: 2026-08-27 · Updated: 2026-08-27 · Language: en
- Canonical page: https://hysenlabs.com/projects/justinbeckwith-linkinator

## What linkinator solves and who should use it

linkinator addresses the recurring problem of broken links in websites, documentation, and local file sets. Broken links degrade user trust, hurt SEO rankings, and break automated documentation builds. The tool is built for developers and site maintainers who want a quick, command-line-driven check that can run locally or inside a CI pipeline. It is not a monitoring service or a visual crawler. The README positions it as a super simple site crawler, and the design reflects that: you point it at a URL or a path, it crawls and validates, and it returns a list of broken links. The target user is someone who already works in a terminal and wants a repeatable check they can script. The project provides both a CLI and a programmatic API, so it fits both interactive use and automated test suites.

## The crawling and validation mechanism

The core mechanism is a crawler that fetches pages, extracts links from any element that includes links, not just anchor tags, and validates each URL by making HTTP requests. The README states it supports redirects, absolute links, relative links, and even markdown files without transpilation. For local files, linkinator stands up a static web server internally, which means it treats a directory of HTML or markdown as if it were a live site. That is a clever approach because it lets the same validation logic handle both remote and local content. The crawler can be told to recurse through links, and it respects a concurrency setting that defaults to 100 simultaneous connections. This high default suggests the tool is built for speed, but it also means you may need to lower the concurrency when checking a fragile site or a rate-limited API. The validation step checks the HTTP status of each link, and you can configure how redirects, fragments, and HTTPS are treated.

## Getting it running: CLI, Docker, and standalone binaries

Installation is straightforward. For Node.js projects, you run npm install linkinator. If you do not have Node.js, the releases page offers standalone binaries that need no runtime dependencies. Docker users can pull ghcr.io/justinbeckwith/linkinator and run the same CLI commands inside a container. For example, docker run ghcr.io/justinbeckwith/linkinator https://jbeckwith.com checks a live site. To check local files, you mount your directory as a volume: docker run -v "$(pwd)":/usr/src/app -w /usr/src/app ghcr.io/justinbeckwith/linkinator . --recurse. The README recommends pinning to a specific version tag for reproducible builds, such as :3.4.0. The basic CLI pattern is linkinator LOCATIONS with flags. A shallow scan is npx linkinator https://jbeckwith.com. For local docs, npx linkinator ./docs runs a top-level check, and adding --recurse goes deeper. The --skip flag accepts a regex and can be repeated, which lets you exclude domains or even invert the match to only scan a specific domain. Output can be formatted as JSON or CSV with --format, which is useful for piping into other tools.

## Configuration file and strict checking modes

Beyond command-line flags, linkinator reads a linkinator.config.json file in the current working directory by default. All options are optional, and the README shows a sample config with keys like concurrency, recurse, skip, format, silent, verbosity, timeout, markdown, checkCss, checkFragments, redirects, requireHttps, and retry settings. For skipping multiple URL patterns, you use an array under skip. The strict checking mode is where linkinator shows its teeth. The command npx linkinator . --recurse --check-css --check-fragments --redirects error --require-https error makes the tool check CSS files, validate fragment identifiers like #section-name, treat any redirect as an error, and reject HTTP links. This is a hard-line mode that can be too aggressive for sites that legitimately use redirects or mixed content. The config file also supports retry options, including retryErrors and retryErrorsCount, which can reduce flaky failures in CI. The presence of these toggles indicates the tool is designed for both permissive and pedantic workflows.

## Sitemap-based scanning and clean URLs

A notable feature is sitemap mode. Instead of discovering pages by following links, you can point linkinator at a sitemap with --sitemap. The tool scans every page declared in the map and validates their links. Sitemap indexes are followed recursively, including entries that use query strings for pagination. For a custom sitemap location, use --sitemap-url, which can be repeated to load multiple maps, but it cannot be combined with --sitemap. If you also pass --recurse, the crawler will go beyond the sitemap seeds and crawl same-site pages linked from those seeds. This is useful for large sites where a full crawl is too slow, or where you only want to validate pages that are officially listed. The README also mentions --clean-urls for extensionless links, which is common in static site generators. The --directory-listing flag includes an automatic directory index file when linking to a directory. These options make linkinator adaptable to different site architectures, but they also add complexity: you need to know which flags apply to your site's structure.

## Limitations and cases where it is the wrong tool

linkinator is a link checker, not a site monitor or an SEO analyzer. It will not tell you why a page ranks poorly, nor will it track link health over time. The README shows no built-in scheduling or alerting, so you must integrate it into your own CI or cron job. The default concurrency of 100 can hammer a small site or trigger rate limiting, so you may need to lower it. The strict checking mode can produce false positives on sites that use JavaScript-driven navigation or that intentionally redirect old URLs. The tool does not execute JavaScript, so links that are only rendered by client-side scripts will not be discovered. For a single-page application, this is a significant gap. The README does not mention any JavaScript rendering or headless browser support, so you should assume it only sees static HTML and links present in the initial response. For local markdown files, the tool works well, but if your markdown contains relative links that depend on a specific build step, those may fail validation. The sitemap mode is a workaround for JavaScript-heavy sites, but it only checks declared pages, not all user-visible pages.

## Alternatives and how they differ

A common alternative is lychee, a broken link checker written in Rust. lychee also provides a CLI and can scan local files, remote URLs, and markdown. The key difference is that lychee is a single binary with no Node.js dependency, which makes it easier to install in minimal CI containers. However, lychee does not offer a Node API or Docker image from the same project, and its configuration model differs. Another alternative is broken-link-checker, an older Node.js library that offers a more granular API but has not seen the same level of maintenance. The README for linkinator does not mention lychee or broken-link-checker, but the comparison is useful: if you are already in a Node ecosystem, linkinator's API and config file fit naturally; if you want a zero-dependency binary, lychee is a leaner choice. linkinator's standalone binaries also remove the Node dependency, but they are distributed as release artifacts, not through a package manager like cargo.

## Maintenance, license, and upgrade considerations

The repository is active, with recent releases in August 2026, including v8.1.0. The project uses semantic-release, as indicated by the badge in the README, which means version numbers follow a predictable pattern and breaking changes are signaled by major version bumps. The license is MIT, which permits commercial use, modification, and redistribution with attribution. There is no copyleft obligation, so you can embed linkinator in a proprietary CI pipeline. The README mentions a Biome badge, suggesting the codebase uses the Biome linter/formatter, which is a modern choice but not directly relevant to users. For upgrades, the major version number is high (v8), and each major release may introduce breaking changes to CLI flags or the config schema. Before upgrading, you should read the release notes and test your existing config file against the new version. The Docker image example pins to version 3.4.0, which is outdated compared to the current v8, so if you follow the README example, you will get an old version. That is a minor documentation inconsistency, but it highlights the need to check the latest release tag when pinning.

## Conclusion

Adopt linkinator if you need a fast, scriptable link checker for a website, a documentation folder, or a CI pipeline, and you want the flexibility of a CLI, a Node API, Docker, and standalone binaries. Skip it if you require a GUI, a hosted service, or deep SEO analytics beyond link validation. Before adopting, verify that the strict modes (check-css, check-fragments, redirects error, require-https error) match your site's actual structure, and test the skip regexes against your real URLs, because a broad skip pattern can hide broken links you intended to catch.

## FAQ

### What is the best link checker?

Linkinator is a broken link checker for live sites, local files and markdown, shipped as an npm package, a standalone binary and a container image. It reads links from any element that carries one rather than only `<a href>`, and handles redirects, absolute and relative links.

### How to check for dead links?

Give the CLI a location: `npx linkinator https://jbeckwith.com` for a live site, `npx linkinator ./docs --recurse` for a directory tree, or `npx linkinator "**/*.md" --markdown` for markdown files. Adding `--format CSV` or `--format json` produces output another program can consume.

### What is a good tool to check for broken links on a website?

For a strict pass, run `npx linkinator . --recurse --check-css --check-fragments --redirects error --require-https error`. Options can live in a `linkinator.config.json` file that the CLI picks up by default, and `--sitemap` scans the pages a site declares instead of discovering them through links.

### How to find websites that link to a URL?

Linkinator does not search the web for pages pointing at a URL. It crawls the locations you name and follows links from there, and since `--skip` takes a regex, `--skip '^(?!http://jbeckwith.com)'` narrows a scan to a single domain instead of the whole outbound link graph.

## Sources

- [Official README](https://github.com/JustinBeckwith/linkinator#readme)
- [Project repository](https://github.com/JustinBeckwith/linkinator)
- [Release notes](https://github.com/JustinBeckwith/linkinator/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/justinbeckwith-linkinator
