Markdown TOC Generator
BetaMake a linked table of contents from the headings in a Markdown file. Pick GitHub or GitLab anchors and the heading levels, then copy the list or download the file with the TOC added.
- Free, no sign-up
- REST + MCP
- Updated
- Reviewed by Olgun Ozoktas
Paste Markdown, or drop a .md file on the box.
On this page, your Markdown is read in your browser and is not uploaded.
How the anchors are made
GitHub
Lowercase, punctuation removed, each space becomes a hyphen. A repeated heading gets -1, -2 and so on.
## Setup & Install#setup--install
GitLab
Lowercase, punctuation removed, spaces become hyphens and a run of hyphens becomes one. Repeats get -1, -2.
## Setup & Install#setup-install
Plain labels
No links. Each entry is the heading text alone, for places where anchors do not work.
## Setup & Install- Setup & Install
How to make a table of contents for a Markdown file
-
Paste or drop the Markdown
Paste the file into the box, or drop a .md file on it. The table of contents appears as you paste. -
Pick the anchor style and levels
GitHub anchors are the default. Choose GitLab for a GitLab repository, or Plain labels for a list without links. Min and Max level set which headings are listed; the default H2 to H4 leaves out a title H1. -
Choose the list format
Pick a dash, a star or a numbered list, and 2 or 4 spaces of indent. Turn on the Table of Contents heading if you want one above the list. -
Copy or insert
Copy TOC puts the list on your clipboard. Download file with TOC saves the whole document with the list inserted at a [TOC] or marker, or after the first heading.
Common uses
A README that has grown long
Design docs and runbooks
Docs hosted on GitLab
An outline without links
Why generate a Markdown table of contents?
Markdown TOC Generator builds a table of contents from the headings in a Markdown document. It reads both heading forms: a line starting with one to six # characters, and a line of text underlined with === or ---. Headings inside fenced and indented code blocks, inside HTML comments and inside front matter are not headings to a renderer, so they are skipped.
Each listed heading gets the anchor the host will give it. GitHub lowercases the heading's text, removes punctuation and turns each space into a hyphen, so ## Setup & Install becomes #setup--install. GitLab does the same and then squeezes runs of hyphens, giving #setup-install. Inline formatting is read the way it renders: ## Using `npm install` links to #using-npm-install. A heading that repeats gets -1, -2 and so on, counted over every heading in the file.
The list nests by heading level, from the shallowest level you list, with a dash, a star or numbers. Download file with TOC writes the list into the document: at a [TOC] line, between <!-- toc --> and <!-- tocstop -->, or after a leading title heading.
It is a one-shot insert. Nothing watches your repository or runs on commit; run the page again after the headings change. The same function is available as a REST API call and an MCP tool for scripts and AI clients.
How it compares
doctoc and the markdown-toc package do this from the command line and can run in a pre-commit hook, which is the right setup for a repository that changes every day. For one file, installing Node and a package is more work than the TOC itself.
Editors such as VS Code have extensions that keep a TOC updated as you type, inside that editor. This page works in any browser and needs nothing installed.
Writing it by hand works until a heading has punctuation, inline code or a duplicate, which is where hand-written anchors usually break.
To see the result rendered, paste the file into Markdown Previewer or convert it with Markdown to HTML. For tables inside the document, there is Markdown Table Generator.
Tips
- Put [TOC] on a line of its own where the list should go. Download file with TOC replaces it.
- Use to keep the list regenerable: the first run adds after the list, and every later run replaces what is between the two markers.
- Two headings with the same text get #setup and #setup-1, the way GitHub numbers them. Repeats are counted across every heading, including ones outside the levels you list.
- Lines starting with # inside code blocks are comments, not headings. Ignore code blocks is on by default; the summary says how many were skipped.
- A numbered list nests with at least 3 spaces, because Markdown needs them under "1. ". With 2 spaces chosen, numbered items use 3.
- Front matter between --- lines at the top of the file is left alone, and the TOC goes after it.