Markdown is a lightweight markup language that lets you write formatted text using plain characters — no GUI, no HTML tags. A # becomes a heading, **word** becomes bold, and [text](url) becomes a clickable link. The resulting file is readable as-is and renders beautifully in any Markdown-aware tool.
Created by John Gruber in 2004, Markdown is now the default format for README files, documentation sites, static site generators, chat messages (Slack, Discord, GitHub comments), and note-taking apps (Obsidian, Notion, Bear).
Markdown in 30 seconds
# Heading 1
## Heading 2
**bold** and *italic* and ~~strikethrough~~
- bullet item
- another item
- nested item
1. ordered item
2. second item
[Link text](https://example.com)

`inline code`
```js
// fenced code block
const x = 42;
Blockquote
--- ← horizontal rule
Write it in any text editor, render it to HTML, PDF, DOCX — the source stays human-readable forever.
---
## Core syntax reference
### Headings
```markdown
# H1
## H2
### H3
#### H4
Six levels available (# through ######). Always add a space after #.
Emphasis
| Syntax | Output | Notes |
|---|---|---|
**bold** |
bold | Or __bold__ |
*italic* |
italic | Or _italic_ |
***bold italic*** |
bold italic | Combine both |
~~strikethrough~~ |
GFM extension | |
`code` |
code |
Inline code |
Lists
- Unordered item ← dash, asterisk, or plus
- Another item
- Nested (2 spaces)
1. Ordered item
2. Second item
1. Nested ordered
Lists need a blank line above if placed after a paragraph.
Links and images
[Link text](https://example.com)
[Link with title](https://example.com "Hover tooltip")
[Reference link][ref-id]
[ref-id]: https://example.com


Code
Inline: `const x = 1`
Fenced block (specify language for syntax highlighting):
```js
function greet(name) {
return `Hello, ${name}!`;
}
```
Tables (GitHub Flavored Markdown)
| Column A | Column B | Column C |
|----------|:--------:|---------:|
| left | center | right |
| aligned | aligned | aligned |
Colons in the separator row control alignment: none = left, :---: = center, ---: = right.
Blockquotes
> This is a blockquote.
> It can span multiple lines.
>
> And multiple paragraphs.
Nest blockquotes with >>.
Task lists (GFM)
- [x] Done item
- [ ] Pending item
- [ ] Another todo
Renders interactive checkboxes on GitHub and many editors.
Markdown flavors
Plain Markdown (original spec) is minimal. Most platforms extend it:
| Flavor | Where used | Notable additions |
|---|---|---|
| CommonMark | Standard base | Resolves ambiguous edge cases |
| GFM (GitHub Flavored Markdown) | GitHub, GitLab | Tables, task lists, strikethrough, autolinks |
| MDX | React/Next.js docs | JSX components inside Markdown |
| MultiMarkdown | Academic writing | Footnotes, citations, math |
| Pandoc Markdown | Document conversion | Extensive extensions for all formats |
When in doubt, write CommonMark-compatible Markdown — it works everywhere.
Parsing Markdown in code
JavaScript (marked + unified ecosystem)
// npm install marked
import { marked } from 'marked';
const md = `# Hello\n\nThis is **Markdown**.`;
const html = marked.parse(md);
// → '<h1>Hello</h1>\n<p>This is <strong>Markdown</strong>.</p>\n'
console.log(html);
// For safe user input (strips dangerous HTML):
import { marked } from 'marked';
import DOMPurify from 'dompurify';
const safeHtml = DOMPurify.sanitize(marked.parse(userInput));
For more complex pipelines (plugins, AST manipulation), use the unified/remark ecosystem:
// npm install unified remark-parse remark-html
import { unified } from 'unified';
import remarkParse from 'remark-parse';
import remarkHtml from 'remark-html';
const file = await unified()
.use(remarkParse)
.use(remarkHtml)
.process('# Hello world');
console.log(String(file)); // <h1>Hello world</h1>
Python (markdown + mistune)
# pip install markdown
import markdown
md = "# Hello\n\nThis is **Markdown**."
html = markdown.markdown(md, extensions=['tables', 'fenced_code'])
print(html)
# <h1>Hello</h1>
# <p>This is <strong>Markdown</strong>.</p>
# GFM-style (strikethrough, task lists):
# pip install mistune
import mistune
md_to_html = mistune.create_markdown(plugins=['strikethrough', 'task_lists'])
print(md_to_html("~~crossed out~~ and - [x] done"))
Go (goldmark)
// go get github.com/yuin/goldmark
package main
import (
"bytes"
"fmt"
"github.com/yuin/goldmark"
"github.com/yuin/goldmark/extension"
"github.com/yuin/goldmark/renderer/html"
)
func main() {
md := goldmark.New(
goldmark.WithExtensions(extension.GFM),
goldmark.WithRendererOptions(html.WithHardWraps()),
)
src := []byte("# Hello\n\nThis is **Markdown**.")
var buf bytes.Buffer
if err := md.Convert(src, &buf); err != nil {
panic(err)
}
fmt.Println(buf.String())
// <h1>Hello</h1>
// <p>This is <strong>Markdown</strong>.</p>
}
goldmark is the standard choice in Go — it's CommonMark-compliant and supports GFM extensions.
PHP (Parsedown)
// composer require erusev/parsedown
require 'vendor/autoload.php';
$Parsedown = new Parsedown();
$Parsedown->setSafeMode(true); // strips raw HTML from user input
$md = "# Hello\n\nThis is **Markdown**.";
echo $Parsedown->text($md);
// <h1>Hello</h1>
// <p>This is <strong>Markdown</strong>.</p>
// For GFM tables and strikethrough:
// composer require erusev/parsedown-extra
$ParsedownExtra = new ParsedownExtra();
echo $ParsedownExtra->text("| A | B |\n|---|---|\n| 1 | 2 |");
Markdown vs alternatives
| Format | Human-readable? | Rich output? | Tooling | Best for |
|---|---|---|---|---|
| Markdown | Excellent | Good (HTML/PDF) | Universal | Docs, READMEs, notes |
| HTML | Poor | Excellent | Universal | Web pages |
| reStructuredText | Good | Excellent (Sphinx) | Python ecosystem | Python docs, scientific |
| AsciiDoc | Good | Excellent (DocBook) | Ruby/Java tooling | Technical manuals |
| LaTeX | Poor | Exceptional (PDF) | TeX distribution | Academic papers |
Markdown wins on simplicity and ubiquity. For complex cross-references, versioned manuals, or precise typesetting, AsciiDoc or LaTeX offer more power.
Quick reference
| Task | Syntax |
|---|---|
| Bold | **text** |
| Italic | *text* |
| Heading | # H1, ## H2, ### H3 |
| Link | [text](url) |
| Image |  |
| Inline code | `code` |
| Code block | ```lang ... ``` |
| Blockquote | > text |
| Unordered list | - item |
| Ordered list | 1. item |
| Horizontal rule | --- |
| Table | | A | B | with separator row |
| Task list | - [x] done / - [ ] todo |
| Strikethrough | ~~text~~ |
| Escape | \* to print a literal * |
6 common Markdown pitfalls
1. Missing blank lines around blocks. Headings, lists, code blocks, and blockquotes all require a blank line above them when placed after a paragraph. Without it, many parsers treat them as continuation text.
Bad: Some text
# This heading won't render correctly
Good: Some text
# This heading renders correctly
2. Inconsistent indentation in nested lists. CommonMark requires exactly 2 or 4 spaces for nesting (parsers disagree). Stick to 2 spaces universally.
3. Trailing spaces for line breaks. A soft line break inside a paragraph requires two trailing spaces (or a \ in some flavors). Just pressing Enter creates a single newline that most parsers collapse into a space — not a new line.
4. Raw HTML inside Markdown. Markdown allows raw HTML, but many renderers (GitHub, documentation sites) sanitize or strip it for security. Don't rely on <div> tags inside Markdown documents that will be rendered on untrusted surfaces.
5. Underscores inside words. snake_case_variable can accidentally render as snake<em>case</em>variable in lenient parsers. CommonMark handles this correctly, but older parsers don't. Use backticks for code: `snake_case_variable`.
6. Different GFM support per platform. Tables, task lists, and strikethrough are GFM extensions — not base Markdown. They work on GitHub, GitLab, and most modern renderers, but may not work in every tool. Test on your target platform.
Frequently asked questions
Is Markdown a programming language? No — it's a markup language (like HTML). It describes formatting, not computation. There's no variables, logic, or execution.
Can I use HTML inside Markdown?
Yes, most parsers pass raw HTML through. However, many platforms sanitize it for security. Limit HTML to cases where Markdown syntax is insufficient (e.g., <kbd>, <details>/<summary>).
What's the difference between .md and .markdown file extensions?
They're identical — both are conventional extensions for Markdown files. .md is more common (shorter to type), especially for README files and documentation.
Does Markdown support math equations?
Not in the base spec. Use KaTeX or MathJax extensions: $E = mc^2$ for inline math and $$...$$ for display math. GitHub now renders math natively.
How do I add a line break inside a paragraph?
Add two spaces at the end of the line, or use a backslash \ (Pandoc, some GFM renderers). Alternatively, separate into two paragraphs with a blank line.
What Markdown editor should I use? For local editing: Obsidian (notes), Typora (WYSIWYG), VS Code (developer). For online: GitHub web editor, StackEdit, Dillinger. For static sites: Hugo, Astro, Docusaurus all process Markdown natively.