Markdown Reference Checker
Build a Python tool that checks the links and images in a folder of Markdown files, such as a project's documentation, and reports what's broken: links to local files or headings that don't exist, web links that return errors, and images that are missing or aren't really images (checked by opening them with Pillow). Results are collected in a pandas table, printed as a summary and saved as a CSV report, and the tool exits with an error code when something is broken, so it can run in a CI pipeline. It's a good first Python project: you'll learn walking folders with pathlib, regular expressions, checking web links with requests (politely, with timeouts), verifying images with Pillow, building reports with pandas, and testing.
- Estimate
- ~8h
- Steps
- 6
- Completed by
- 0
- Proposed by
- codeseed.app
pandas · Pillow
Project roadmap
- 01
Define what the tool checks
~1hWrite README.md: the command (python checklinks.py DOCS_FOLDER, with --no-external, --timeout and --report report.csv), what counts as broken (a missing local file, a missing #heading anchor, a web link with an error status or no answer, and an image that's missing or can't be opened), and the exit codes (0 when nothing is broken and 1 otherwise). Create a virtual environment with requests, pandas, Pillow and pytest. Done when: README.md defines the checks and options.
- 02
Find links and images
~1.5hFind all .md files with pathlib's rglob, read them line by line, and extract links [text](target) and images  with regular expressions, recording the file and line number. Skip lines inside fenced code blocks (between ``` lines). Done when: running on a test folder lists every link and image with its location.
- 03
Check local links and images
~1.5hResolve relative targets against the Markdown file's folder and check they exist. For #anchors, read the target file's headings and turn them into anchors the way GitHub does (lowercase, spaces to dashes and most punctuation removed). For images, open them with Pillow (Image.open and verify()) to confirm they're real images, recording the size. Done when: missing files, wrong anchors and broken images are all detected.
- 04
Check web links
~1.5hCheck each unique http and https URL once with requests (HEAD first, then GET when HEAD isn't allowed), with a timeout, a descriptive user agent and a short pause between requests to the same site. Record the status code or the error. Skip them all with --no-external. Done when: broken and working web links are classified correctly, and each URL is requested only once.
- 05
Report with pandas
~1hPut all results in a pandas DataFrame (file, line, kind, target, status and reason), print a summary of broken items grouped by kind and file, and save the full table as CSV with --report. Exit with code 1 when anything is broken. Done when: the summary and CSV list every broken item.
- 06
Test it
~1.5hWrite pytest tests with a temporary folder containing Markdown files, a real image, a fake image (a text file named .png) and missing targets, and fake the web checks with monkeypatch or the responses library: link extraction, code blocks skipped, anchors, images and web statuses. Done when: pytest passes without network access.
Resources
Ready to build this?
Get a GitHub repo and start building. Your AI reviewer checks each step as you go.
Tech stack