📑 Markdown TOC Generator
Paste your Markdown and instantly generate a nested table of contents from h1–h6 headings. Supports GitHub and GitLab slug styles, Markdown/HTML/plain output, depth limits, and numbered lists.
🔒 About Privacy
- ・Markdown is parsed only in your browser
- ・Your text is never sent to any server
- ・No signup, no login, no payment ever
⚙ Options
Preview (rendered HTML)
📖 Where people get stuck
Reads the headings out of Markdown and builds a table of contents, with a choice of output format (plain, slug or custom), which heading levels to include, numbered lists, and whether to skip h1. Everything runs in the browser. The rule for generating anchor links differs from platform to platform — there is no guarantee that the links produced here will work where you paste them, and non-Latin headings in particular are handled very differently across environments.
| Case | What happens | What to do |
|---|---|---|
| Clicking an entry in the table of contents goes nowhere | The rule for turning a heading into an id — slugification — differs by platform: which punctuation is removed, how runs of spaces are handled, what happens to emoji, and above all how non-Latin text is treated. GitHub keeps Japanese in the id and percent-encodes it in the link, whereas some environments drop it entirely and fall back to a numbered section-1. On top of that, the same Markdown yields different ids on GitHub, GitLab, Qiita, Zenn, VitePress and Docusaurus — so you cannot produce correct links without first deciding where they will live. |
Verify by actually clicking at the destination — it is the only reliable check. On GitHub, hovering over a heading reveals a link icon on its left, and the link you copy from there is the correct one. Confirm one and you know the rule; apply the same transformation to the rest. And once published, click every entry at least once — in a long article especially, a table of contents with dead links is worse than none, since leading a reader to a link that does nothing is a worse experience than not offering one. If the same text goes out on several platforms, giving up on links and shipping a plain-text list is a perfectly realistic decision. |
| Duplicate headings all link to the first one | Headings such as Summary or Caveats recur several times in one article. Most platforms avoid the collision by appending a counter to the second and subsequent ids — -1, -2 and so on, but a generator that does not know the rule produces the same link for all of them: click any of three Summary entries and you land on the first. The numbering is not standardised either — some implementations start at -1 and others at -2. From the reader point of view the awkward part is that the link works and goes to the wrong place, which makes the breakage hard to notice. |
Make the headings unique. Writing Summary of the auth changes and Summary of the performance work rather than Summary alone not only removes the link problem but makes the table of contents informative at a glance. In other words this is not a technical workaround but an improvement to the writing — the moment the same word appears three times in a contents list, its value to the reader has already dropped. If you genuinely must repeat a heading, embed an HTML <a id="..."> by hand and manage the ids yourself — that works on any platform which lets raw HTML through, though not somewhere like Slack that does not interpret HTML at all. |
| The table of contents is so long it hurts | Include h4 and h5 and the contents alone fill a screen. When the first thing a reader meets is a thirty-line bulleted list, many leave before reaching the text. The purpose of a table of contents is to convey the shape of the whole at a glance, so one that cannot be taken in at a glance is not doing its job. Beyond that, its length is a reflection of the heading structure itself: passing twenty entries means either too much has been crammed into one article, or headings are being used in place of paragraphs. | Limit the contents to h2 and h3 — this tool minimum and maximum level settings do exactly that. h1 is the article title, so turn on skip h1; two h1 elements in one document is not correct HTML structure to begin with. If it still exceeds twenty entries, consider splitting the article — a long table of contents is a symptom, and the diagnosis is that the article has spread beyond what it can cover. Judging by whether a reader can decide in five seconds which section they need settles the right granularity quickly. |
Check first whether you need a table of contents in the body at all. Since 2021 GitHub has shown an outline of the headings from a button at the top right of a README, and Zenn, Qiita and most static site generators — VitePress, Docusaurus, Astro — generate one from the headings and display it alongside the text as you scroll. In other words, writing one by hand is only necessary where the environment does not provide it. Understand the cost of embedding one, too: every heading you change means editing the contents by hand, and eventually you will forget. A stale table of contents is worse than none, because it directs readers to sections that no longer exist. For a document you will keep updating, either regenerate the contents in CI or decide not to have one — running something like markdown-toc from a pre-commit hook removes the manual step entirely. A table of contents written once and then abandoned is the worst of the options.
📖 How to Use
-
1
Paste MarkdownPaste your full Markdown into the left text area.
-
2
Adjust optionsPick output format (Markdown / HTML / plain), slug style, min/max heading level, and numbering.
-
3
Copy or downloadCopy the generated TOC to your clipboard, or download as .md / .html / .txt.
❓ Frequently Asked Questions
Will the anchors match GitHub exactly?
Is my Markdown sent to your server?
Are # signs inside code blocks ignored?
🔗 Related Tools
🐛 Found a bug or issue with this tool?
Free to use, no signup. Even just the steps to reproduce are helpful. Reports go directly to the operator and help us fix issues.
Thanks for your report!
Your report has been delivered to the operator and will be used to improve the tool.