⚡ A fast, async, stream-based link checker written in Rust.
Finds broken hyperlinks and mail addresses inside Markdown, HTML,
reStructuredText, or any other text file or website!
Available as a command-line utility, a library and a GitHub Action.
Table of Contents
- Development
- Installation
- Features
- Commandline usage
- Library usage
- GitHub Action Usage
- Pre-commit Usage
- Contributing to lychee
- Troubleshooting and Workarounds
- Users
- Credits
- License
Development
After installing Rust use Cargo for building and testing.
On Linux the OpenSSL package is required to compile reqwest, a dependency of lychee.
For Nix we provide a flake so you can use nix develop and nix build.
Installation
Arch Linux
OpenSUSE Tumbleweed
Ubuntu
macOS
Via Homebrew:
Via MacPorts:
Docker
NixOS
Nixpkgs
-
lycheepackage for configurations, Nix shells, etc. -
Let Nix check a packaged site with
testers.lycheeLinkCheck{ site = …; }
FreeBSD
Scoop
Termux
Alpine Linux
# available for Alpine Edge in testing repositories
WinGet (Windows)
Chocolatey (Windows)
Conda
Pre-built binaries
We provide binaries for Linux, macOS, and Windows for every release.
You can download them from the releases page.
Cargo
Build dependencies
On APT/dpkg-based Linux distros (e.g. Debian, Ubuntu, Linux Mint and Kali Linux)
the following commands will install all required build dependencies, including
the Rust toolchain and cargo:
|
Compile and install lychee
Feature flags
Lychee supports several feature flags:
native-tlsenables the platform-native TLS crate native-tls.vendored-opensslcompiles and statically links a copy of OpenSSL. See the corresponding feature of the openssl crate.rustls-tlsenables the alternative TLS crate rustls.email-checkenables checking email addresses using the check-if-email-exists crate. This feature requires thenative-tlsfeature.check_example_domainsallows checking example domains such asexample.com. This feature is useful for testing.
By default, native-tls and email-check are enabled.
Features
This comparison is made on a best-effort basis. Please create a PR to fix outdated information.
| lychee | awesome_bot | muffet | broken-link-checker | linkinator | linkchecker | markdown-link-check | fink | |
|---|---|---|---|---|---|---|---|---|
| Language | Rust | Ruby | Go | JS | TypeScript | Python | JS | PHP |
| Async/Parallel | ||||||||
| JSON output | ||||||||
| Static binary | ️ |
|||||||
| Markdown files | ||||||||
| HTML files | ||||||||
| Text files | ||||||||
| Website support | ||||||||
| Chunked encodings | ||||||||
| GZIP compression | ||||||||
| Basic Auth | ||||||||
| Custom user agent | ||||||||
| Relative URLs | ||||||||
| Anchors/Fragments | ||||||||
| Skip relative URLs | ||||||||
| Include patterns | ||||||||
| Exclude patterns | ||||||||
| Handle redirects | ||||||||
| Ignore insecure SSL | ||||||||
| File globbing | ||||||||
| Limit scheme | ||||||||
| Custom headers | ||||||||
| Summary | ||||||||
HEAD requests |
||||||||
| Colored output | ||||||||
| Filter status code | ||||||||
| Custom timeout | ||||||||
| E-mail links | ||||||||
| Progress bar | ||||||||
| Retry and backoff | ||||||||
| Skip private domains | ||||||||
| Use as library | ||||||||
| Quiet mode | ||||||||
| Config file | ||||||||
| Cookies | ||||||||
| Recursion | ||||||||
| Amazing lychee logo |
1 Other machine-readable formats like CSV are supported.
Commandline usage
Recursively check all links in supported files inside the current directory
You can also specify various types of inputs:
# check links in specific local file(s):
# check links on a website:
# check links in directory but block network requests
# check links in a remote file:
# check links in local files via shell glob:
# check links in local files (lychee supports advanced globbing and ~ expansion):
# ignore case when globbing and check result for each link:
# check links from epub file (requires atool: https://www.nongnu.org/atool)
|
lychee parses other file formats as plaintext and extracts links using linkify. This generally works well if there are no format or encoding specifics, but in case you need dedicated support for a new file format, please consider creating an issue.
Docker Usage
Here's how to mount a local directory into the container and check some input with lychee.
- The
--initparameter is passed so that lychee can be stopped from the terminal. - We also pass
-itto start an interactive terminal, which is required to show the progress bar. - The
--rmremoves not used anymore container from the host after the run (self-cleanup). - The
-w /inputpoints to/inputas the default workspace - The
-v $(pwd):/inputdoes local volume mounting to the container for lychee access.
By default a Debian-based Docker image is used. If you want to run an Alpine-based image, use the
latest-alpinetag. For example,lycheeverse/lychee:latest-alpine
Linux/macOS shell command
Windows PowerShell command
docker run --init -it --rm -w /input -v ${PWD}:/input lycheeverse/lychee README.md
GitHub Token
To avoid getting rate-limited while checking GitHub links, you can optionally
set an environment variable with your GitHub token like so GITHUB_TOKEN=xxxx,
or use the --github-token CLI option. It can also be set in the config file.
Here is an example config file.
The token can be generated on your GitHub account settings page. A personal access token with no extra permissions is enough to be able to check public repo links.
For more scalable organization-wide scenarios you can consider a GitHub App. It has a higher rate limit than personal access tokens but requires additional configuration steps on your GitHub workflow. Please follow the GitHub App Setup example.
Commandline Parameters
There is an extensive list of command line parameters to customize the behavior. See below for a full list.
Exit codes
0 Success. The operation was completed successfully as instructed.
1 Missing inputs or any unexpected runtime failures or configuration errors
2 Link check failures. At least one non-excluded link failed the check.
3 Encountered errors in the config file.
Ignoring links
You can exclude links from getting checked by specifying regex patterns
with --exclude (e.g. --exclude example\.(com|org)).
Here are some examples:
# Exclude LinkedIn URLs (note that we match on the full URL, including the schema to avoid false-positives)
# Exclude LinkedIn and Archive.org URLs
# Exclude all links to PDF files
# Exclude links to specific domains
# Exclude links with certain URL parameters
# Exclude all mailto links
For excluding files/directories from being scanned use lychee.toml
and exclude_path.
= ["some/path", "*/dev/*"]
If a file named .lycheeignore exists in the current working directory, its
contents are excluded as well. The file allows you to list multiple regular
expressions for exclusion (one pattern per line).
For more advanced usage and detailed explanations, check out our comprehensive guide on excluding links.
Caching
If the --cache flag is set, lychee will cache responses in a file called
.lycheecache in the current directory. If the file exists and the flag is set,
then the cache will be loaded on startup. This can greatly speed up future runs.
Note that by default lychee will not store any data on disk.
Library usage
You can use lychee as a library for your own projects! Here is a "hello world" example:
use Result;
async
This is equivalent to the following snippet, in which we build our own client:
use ;
async
The client builder is very customizable:
let client = builder
.includes
.excludes
.max_redirects
.user_agent
.allow_insecure
.custom_headers
.method
.timeout
.github_token
.scheme
.accepted
.build
.client?;
All options that you set will be used for all link checks.
See the builder documentation
for all options. For more information, check out the examples
directory. The examples can be run with cargo run --example <example>.
GitHub Action Usage
A GitHub Action that uses lychee is available as a separate repository: lycheeverse/lychee-action which includes usage instructions.
Pre-commit Usage
Lychee can also be used as a pre-commit hook.
# .pre-commit-config.yaml
repos:
- repo: https://github.com/lycheeverse/lychee.git
rev: v0.15.1
hooks:
- id: lychee
# Optionally include additional CLI arguments
args:
Rather than running on staged-files only, Lychee can be run against an entire repository.
- id: lychee
args:
pass_filenames: false
Contributing to lychee
We'd be thankful for any contribution.
We try to keep the issue tracker up-to-date so you can quickly find a task to work on.
Try one of these links to get started:
For more detailed instructions, head over to CONTRIBUTING.md.
Troubleshooting and Workarounds
We collect a list of common workarounds for various websites in our troubleshooting guide.
Users
Here is a list of some notable projects who are using lychee.
- https://github.com/InnerSourceCommons/InnerSourcePatterns
- https://github.com/opensearch-project/OpenSearch
- https://github.com/ramitsurana/awesome-kubernetes
- https://github.com/papers-we-love/papers-we-love
- https://github.com/pingcap/docs
- https://github.com/microsoft/WhatTheHack
- https://github.com/nix-community/awesome-nix
- https://github.com/balena-io/docs
- https://github.com/launchdarkly/LaunchDarkly-Docs
- https://github.com/pawroman/links
- https://github.com/analysis-tools-dev/static-analysis
- https://github.com/analysis-tools-dev/dynamic-analysis
- https://github.com/mre/idiomatic-rust
- https://github.com/bencherdev/bencher
- https://github.com/sindresorhus/execa
- https://github.com/tldr-pages/tldr-maintenance
- https://github.com/git-ecosystem/git-credential-manager
- https://github.com/git/git-scm.com
- https://github.com/OWASP/threat-dragon
- https://github.com/oxc-project/oxc
- https://github.com/hugsy/gef
- https://github.com/mermaid-js/mermaid
- https://github.com/hashicorp/consul
- https://github.com/Unleash/unleash
- https://github.com/fastify/fastify
- https://github.com/nuxt/nuxt
- https://github.com/containerd/containerd
- https://github.com/rolldown/rolldown
- https://github.com/rerun-io/rerun
- https://github.com/0xAX/asm
- https://github.com/mainmatter/100-exercises-to-learn-rust
- https://github.com/GoogleCloudPlatform/generative-ai
- https://github.com/DioxusLabs/dioxus
- https://github.com/ministryofjustice/modernisation-platform
- https://github.com/orhun/binsider
- https://github.com/NVIDIA/aistore
- https://github.com/gradle/gradle
- https://github.com/forus-labs/forui
- https://github.com/FreeBSD-Ask/FreeBSD-Ask
- https://github.com/prosekit/prosekit
- https://github.com/lycheeverse/lychee (yes, lychee is checked with lychee 🤯)
If you are using lychee for your project, please add it here.
Credits
The first prototype of lychee was built in episode 10 of Hello Rust. Thanks to all GitHub and Patreon sponsors for supporting the development since the beginning. Also, thanks to all the great contributors who have since made this project more mature.
License
lychee is licensed under either of
- Apache License, Version 2.0, (LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or https://opensource.org/licenses/MIT)
at your option.