# Markdown TOC Generator - GitHub-Anchor Table of Contents (`eliai/markdown-toc-generator`) Actor

Paste-ready TOC for any markdown doc or URL: GitHub-compatible anchors, nested indentation, duplicate headings deduped, code fences ignored, setext + ATX parsed, links stripped from heading text. Up to 50 docs per run. $0.0008 per document, unfetchable URLs never charged.

- **URL**: https://apify.com/eliai/markdown-toc-generator.md
- **Developed by:** [Broke to Built](https://apify.com/eliai) (community)
- **Categories:** Developer tools, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.64 / 1,000 generated tocs

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Markdown TOC Generator — GitHub-Anchor Table of Contents by API

Generate a correct, paste-ready table of contents for any markdown document — GitHub-compatible anchors, nested indentation, duplicate headings deduped — from raw markdown or a URL. Up to 50 documents per run, online, by API, or as an agent tool via Apify MCP.

Hand-maintaining a TOC drifts out of date the day someone renames a heading; naive generators break on the details (code fences containing `#`, setext `===` headings, links inside headings, two sections with the same name). This one handles all of those — and each behavior is asserted by our automated release test.

### What you get

- **toc** — ready-to-paste markdown: nested `- [Heading](#anchor)` lines, indented by level
- **outline** — the same data structured: `{level, text, slug}` per heading
- **headingCount**, plus fetch metadata for URL inputs
- Correctness details: ATX (`#`) and setext (`===`/`---`) headings both parsed; fenced code blocks skipped; inline links/emphasis stripped from heading text; GitHub slug rules (unicode kept, punctuation dropped); duplicate anchors deduped `setup`, `setup-1`, ...
- **minDepth/maxDepth** — window the levels included (default 1-3)
- **Fail-soft**: an unfetchable URL never fails the run — it returns `{ok: false, error}` and is **never charged**.

### Input

```json
{ "url": "https://raw.githubusercontent.com/apify/apify-sdk-js/master/README.md", "maxDepth": 3 }
```

Or raw text: `{ "markdown": "# Title\n## Section..." }`. Bulk via `urls` array.

### Output (real run, trimmed)

```json
{
  "ok": true,
  "headingCount": 5,
  "toc": "- [Intro](#intro)\n- [Setext Title](#setext-title)\n  - [Setup](#setup)\n    - [Linked step](#linked-step)\n  - [Setup](#setup-1)",
  "outline": [
    { "level": 1, "text": "Intro", "slug": "intro" },
    { "level": 2, "text": "Setup", "slug": "setup" },
    { "level": 2, "text": "Setup", "slug": "setup-1" }
  ]
}
```

### Pricing

**$0.0008 per document parsed.** No start fee. Unfetchable URLs are never charged.

No direct paid markdown-TOC incumbent was found on the store (2026-08-07 search across "markdown toc", "table of contents" — results are converters and crawlers). Pricing is cost-plus at ~5x measured run cost.

### Honest limits

- Anchor slugs follow GitHub's rules; other renderers (GitLab, some SSGs) differ slightly on punctuation edge cases — the `outline` gives you text+level to re-slug for any target.
- URL inputs are fetched as plain text — point at RAW markdown (e.g. `raw.githubusercontent.com`), not an HTML-rendered page.
- The TOC is generated, not inserted — splice it into your document wherever you keep it.

### FAQ

**Do code blocks containing # break it?**
No — fenced blocks (\`\`\` and ~~~) are tracked and their contents ignored. Asserted in our release test.

**What about two sections with the same name?**
Deduped exactly like GitHub: second `## Setup` becomes `#setup-1`, so every TOC link lands on the right section.

**Are setext headings (underlined with === or ---) supported?**
Yes, as h1/h2 respectively — plenty of older READMEs use them.

**Can I generate TOCs for a whole docs repo?**
Yes — pass up to 50 raw-file URLs via `urls`; each document gets its own record.

**Why did some rows come back `ok: false`?**
The URL 404'd or timed out. Recorded with the exact error, never charged.

### Use from code or AI agents

```bash
curl -s "https://api.apify.com/v2/acts/EliAI~markdown-toc-generator/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
  -X POST -H 'Content-Type: application/json' \
  -d '{"url": "https://raw.githubusercontent.com/your/repo/main/README.md"}'
```

Agents: connect [Apify MCP](https://mcp.apify.com) and call the `EliAI/markdown-toc-generator` tool.

- **Capability:** generate GitHub-anchor TOC + structured outline from raw markdown or markdown URLs
- **Required input:** `markdown` (string) or `url`/`urls`
- **Returns:** one record per document; `toc` is paste-ready markdown, `outline` is structured
- **Bounded:** 50 documents per run, depth window 1-6; failures isolate per document
- **Side effects:** none

# Actor input Schema

## `markdown` (type: `string`):

Paste raw markdown to generate a table of contents from. Provide this OR a URL.

## `url` (type: `string`):

URL of a raw markdown document (e.g. a raw GitHub README). Provide this OR pasted markdown.

## `maxDepth` (type: `integer`):

Deepest heading level to include in the TOC (1 = #, 6 = ######).

## `minDepth` (type: `integer`):

Shallowest heading level to include in the TOC.

## `urls` (type: `array`):

Multiple raw-markdown URLs to process in one run — one TOC record each.

## Actor input object example

```json
{
  "markdown": "# Getting Started\n\n## Installation\n\n### Requirements\n\n## Usage\n\n## API Reference\n\n### Methods\n\n### Events",
  "url": "https://raw.githubusercontent.com/apify/apify-sdk-js/master/README.md",
  "maxDepth": 3,
  "minDepth": 1,
  "urls": [
    "https://raw.githubusercontent.com/apify/apify-sdk-js/master/README.md"
  ]
}
```

# Actor output Schema

## `results` (type: `string`):

Every item this run produced, as JSON.

## `resultsCsv` (type: `string`):

The same items as a spreadsheet-ready CSV.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "markdown": `# Getting Started

## Installation

### Requirements

## Usage

## API Reference

### Methods

### Events`,
    "url": "https://raw.githubusercontent.com/apify/apify-sdk-js/master/README.md",
    "urls": [
        "https://raw.githubusercontent.com/apify/apify-sdk-js/master/README.md"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("eliai/markdown-toc-generator").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "markdown": """# Getting Started

## Installation

### Requirements

## Usage

## API Reference

### Methods

### Events""",
    "url": "https://raw.githubusercontent.com/apify/apify-sdk-js/master/README.md",
    "urls": ["https://raw.githubusercontent.com/apify/apify-sdk-js/master/README.md"],
}

# Run the Actor and wait for it to finish
run = client.actor("eliai/markdown-toc-generator").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "markdown": "# Getting Started\\n\\n## Installation\\n\\n### Requirements\\n\\n## Usage\\n\\n## API Reference\\n\\n### Methods\\n\\n### Events",
  "url": "https://raw.githubusercontent.com/apify/apify-sdk-js/master/README.md",
  "urls": [
    "https://raw.githubusercontent.com/apify/apify-sdk-js/master/README.md"
  ]
}' |
apify call eliai/markdown-toc-generator --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,eliai/markdown-toc-generator"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/dG106ySkKF7Cwg50s/builds/QCj5nrI1J5Xo0BwcV/openapi.json
