100% in-browser · nothing uploaded · no sign-up
Markdown to JSON Converter
Paste any Markdown or GFM document and get a clean, copyable JSON tree instantly — a generic Markdown AST or API-ready Notion blocks. Ideal for agent context, RAG pipelines and CMS importers.
Live parsing is debounced, so there is no Run button — the JSON on the right is always the current document.
JSON result
waiting for input1
Parsed JSON appears here as you type.
How it works
Three steps, all client-side.
Drop a README, a note export or raw LLM output into the box. Frontmatter, tables and task lists are recognised.
Stay on the generic Markdown AST, or switch to Notion blocks where headings, lists, quotes, code and tables become heading_1, bulleted_list_item, table…
One click copies the exact JSON shown on screen; Download writes it to document.json or notion-blocks.json via a Blob URL.
What you get
Every node is a plain object with a type key and, where relevant, children.
Markdown AST
document · heading · paragraph · bullet_list · ordered_list · list_item · blockquote · code_block · table · thematic_break · html_block, plus inline text · strong · em · strikethrough · code_inline · link · image · softbreak.
{
"type": "heading",
"depth": 1,
"children": [
{
"type": "strong",
"children": [
{ "type": "text", "value": "Release notes" }
]
}
]
}Notion blocks
An array of object: "block" items with real Notion types, rich-text annotations, task checkboxes and table rows — paste it straight into a blocks request.
{
"object": "block",
"type": "heading_1",
"heading_1": {
"rich_text": [
{
"type": "text",
"text": { "content": "Release notes" },
"annotations": {
"bold": false, "italic": false,
"strikethrough": false, "code": false
}
}
],
"is_toggleable": false
}
}A leading --- block becomes a top-level frontmatter object (strings, numbers, booleans, lists, nesting, block scalars). Unparseable YAML is preserved verbatim as frontmatter_raw instead of failing.
An unterminated code fence, a broken table or stray YAML never throws: the remaining lines still become paragraphs and a non-blocking warning names the likely line.
Embedded HTML becomes an html_block / html_inline node. In Notion mode it lands in a paragraph with the code annotation so nothing is silently dropped.
FAQ
Is my Markdown uploaded anywhere?
No. Parsing, formatting, copying and downloading all happen in this tab, and the page makes no network request — keep DevTools open and watch the Network panel stay empty.
How do I send the JSON to Notion?
Choose Notion blocks, then POST the array as the children of a page or block. The API accepts at most 100 blocks per request, so chunk a long array: {"children": blocks.slice(0, 100)}.
Why do h4, h5 and h6 become heading_3?
Notion only offers three heading levels. Deeper Markdown headings keep their text and map to heading_3; the AST keeps the exact depth value.
What happens with malformed Markdown?
The parser never fails the conversion. Unclosed fences, broken tables and invalid YAML produce a warning banner naming the line, and the rest of the document is still converted.
Is there a size limit?
There is a 1 MB soft cap. Larger documents are still parsed, but the download stays locked behind a confirmation checkbox so a runaway paste cannot freeze your phone.
What about very deep lists?
List nesting is clamped at 20 levels and the footer tells you when that happened, which keeps recursion (and the Notion tree) finite and crash-free.