Tutorials 21 min read

A Space in the Note Name Breaks the Markdown Link — and the Two Ways to Write It

MMNMNOTE
markdownmarkdown linkscommonmarkfile namesgithubpandocportability

In CommonMark, a space ends a link's path, so [agenda](Meeting notes.md) is not a link at all — GitHub prints it as plain text. Two spellings work in every renderer we tested: angle brackets, [agenda](<Meeting notes.md>), and %20, [agenda](Meeting%20notes.md). Prefer the angle brackets. They keep the note's name readable to search.

The question is common enough to have a view count. Five Stack Exchange questions about links to files with spaces in their names — the oldest asked in January 2016 — had 90,341 views between them on 2026-11-07.1 The most-read, on Super User, asks it plainly: "How do I add a hyperlink with spaces in it using markdown?" It alone had 41,884.

The note-keeper's version of the problem is the larger one. Many note apps name the file after the note's title, and titles have spaces. A link that works inside the app breaks the day the folder is opened somewhere else — pushed to GitHub, built into a site, read in another editor.

An earlier piece here made the case for plain [text](path) links over wikilinks and gave spaces one line: they "need URL-encoding (%20) for many readers." That line holds. This piece adds the second valid form — and the reason to prefer it.

On 2026-11-07 we rendered 23 link, image and reference forms through nine settings: GitHub's own renderer, markdown-it 15.0.3, commonmark.js 0.31.2, marked 18.1.3, pandoc 3.13 with four readers (markdown, gfm, commonmark, markdown_strict) and John Gruber's original Markdown.pl 1.0.1, from 2004.2 It is one day's measurement of named versions, not a law.


Because CommonMark, the specification GitHub and many modern renderers follow, ends a link's destination at the first space. Whatever comes after is no longer the path, so the whole [text](...) falls back to plain text. The only way to keep a raw space inside the destination is to wrap the path in angle brackets.

The spec says it in one sentence, then shows it in two examples: "The destination can only contain spaces if it is enclosed in pointy brackets:"3

Example 488   [link](/my uri)      →   <p>[link](/my uri)</p>
Example 489   [link](</my uri>)    →   <p><a href="/my%20uri">link</a></p>

Example 488 is not a broken link. It is not a link at all — the parser gives up on the link syntax and prints the brackets as typed. Example 489 is the same path with two characters added, and the renderer writes the space out as %20.

That is the second spelling. %20 is not a Markdown feature; it is how a URL writes a space. The same spec points at it in its section on autolinks: "If the URI includes these characters, they must be percent-encoded (e.g. %20 for a space)."4 A percent-encoded path contains no space, so the destination ends where it should.

A file system allows a space in a name. Link syntax needs to be told where the name ends.


The table: 13 ways to write the path, nine renderers

Two forms were links everywhere we tested: angle brackets and %20. A bare space was a link in only three of nine settings, all of them pandoc readers or the 2004 original. The backslash, the plus sign and a bare-space reference definition each fail somewhere — or point at the wrong file. Parentheses add one more failure: Markdown.pl.

FormExampleRight target inWhere it fails
Bare space[a](my note.md)3 of 9Plain text on GitHub, markdown-it, commonmark.js, marked, pandoc gfm and commonmark
Angle brackets[b](<my note.md>)9 of 9—
%20[c](my%20note.md)9 of 9—
Backslash before the space[d](my\ note.md)1 of 9 (pandoc markdown)Plain text in six; the wrong file in markdown_strict and Markdown.pl
Plus sign[g](my+note.md)0 of 9A link in all nine — to a file named my+note.md
Bare-space image![e](my image.png)2 of 9Plain text in six; Markdown.pl makes a link with a stray !
Image in angle brackets![f](<my image.png>)8 of 9Markdown.pl
Reference definition, bare space[h]: my note.md2 of 9Not a definition in seven — printed as a paragraph
Reference definition, angle brackets[i]: <my note.md>8 of 9Markdown.pl
Parentheses, bare space[j](notes/Meeting (2026).md)2 of 9Plain text in six; Markdown.pl cuts at the first )
Parentheses, angle brackets[k](<notes/Meeting (2026).md>)8 of 9Markdown.pl cuts at the first )
Parentheses, %20[l](Meeting%20notes%20(2026).md)8 of 9Markdown.pl cuts at the first )
Everything encoded[m](Meeting%20notes%20%282026%29.md)9 of 9—

The three settings that accepted a bare space were pandoc's markdown and markdown_strict readers and Markdown.pl. Every CommonMark-family setting — GitHub, markdown-it, commonmark.js, marked, pandoc gfm and pandoc commonmark — printed it as text.

pandoc counts as two renderers here, and that is the trap. Its default markdown reader accepted the bare space; the same file read with -f gfm printed it as text. A note that converts cleanly in one pandoc command can still break on GitHub.

Where a form works, the HTML differs in one small detail. GitHub, markdown-it, commonmark.js, marked and pandoc's markdown and markdown_strict readers turned <my note.md> into href="my%20note.md". pandoc's gfm and commonmark readers and Markdown.pl kept the raw space, href="my note.md".

That still works when clicked. The WHATWG URL Standard builds its path percent-encode set on a set "consisting of the C0 control percent-encode set and U+0020 SPACE" — so a browser following my note.md requests my%20note.md.5


Take one note named the way an app names it from a title: Meeting notes (2026).md. Five links point at it below, with what the nine settings did. Only the fully encoded form was a link everywhere. Angle brackets and %20 failed only in the 2004 Markdown.pl, which ends the link at the first closing parenthesis.

Note on disk:  Meeting notes (2026).md

[a](Meeting notes (2026).md)            plain text in 6 of 9 settings
[b](<Meeting notes (2026).md>)          a link in 8 of 9 — Markdown.pl cuts it short
[c](Meeting%20notes%20(2026).md)        a link in 8 of 9 — Markdown.pl cuts it short
[d](Meeting%20notes%20%282026%29.md)    a link in 9 of 9
[e](Meeting+notes+(2026).md)            a link in 8 of 9 — to a different file name

"Cuts it short" is literal. For [b], Markdown.pl wrote href="Meeting notes (2026" and left .md>) as text after the link.2 The link exists; it points at a file that does not.

The fully encoded line is what the Markdown cheat sheet here already recommends: %20 for spaces, %28 and %29 for parentheses. It was the only spelling that survived all nine. It is also the one nobody can read at a glance — which is the cost the next section weighs.

A link into a heading of that note adds a second question after the #. [actions](<Meeting notes.md#action-items>) kept the fragment intact in all nine settings. What #action-items ought to be is a separate problem, covered in The Same Heading Gets a Different Link in Every App.


Angle brackets or %20: which should a vault use?

Use angle brackets in notes. Both forms are valid CommonMark, and both worked in all nine settings for a plain name. The difference shows up when you search: <Meeting notes.md> contains the note's name as typed, so a plain-text search finds it. Meeting%20notes.md does not, and a search for "Meeting notes" walks past it.

We tested it with three one-line files: one angle-bracket link, one %20 link and one wikilink.

printf 'Agenda in [the meeting](<Meeting notes.md>).\n'    > a.md
printf 'Agenda in [the meeting](Meeting%%20notes.md).\n'   > b.md
printf 'Agenda in [[Meeting notes]].\n'                    > c.md

grep -rn "Meeting notes" .
# c.md:1:Agenda in [[Meeting notes]].
# a.md:1:Agenda in [the meeting](<Meeting notes.md>).

grep and ripgrep 15.1.0 both returned two of the three files.2 The %20 link is still there — it is spelled differently from the name. Search for Meeting%20notes and it turns up, if you remember to.

That matters most in a vault you navigate by searching rather than by folders. "What links to this note?" is a search for its name. An encoded link drops out of the answer.

A link is text, too. It should be findable as text.

Pick %20 instead when the file must render in Markdown.pl or another engine that predates CommonMark, or when a name holds parentheses and you need all nine — then encode those as well.


What Obsidian and VS Code write

Two popular editors pick different forms, and both are correct. Obsidian's help tells you to URL-encode Markdown-format links, so a space becomes %20. VS Code, when you drop or paste a file into a Markdown document, wraps any path containing whitespace in angle brackets. Whichever app you use, check which form it writes.

Obsidian. Its Internal links help page, on links written in Markdown format rather than as wikilinks, gives the example directly: "For example, blank spaces become %20."6 That is a valid, portable choice — the table above shows it working in all nine settings.

A user reports that Obsidian also opens angle-bracket links: "Wrapping the link target in angle brackets works," they wrote on the Obsidian forum in February 2026.7 Renaming is the open question. A forum thread about angle-bracket links on rename was opened in June 2021; in October 2023, on Obsidian 1.4.16, another user added that "Obsidian keeps mangling angle-bracketed file links on file renames despite otherwise supporting this standard CommonMark format."8

We did not test the current version, and Obsidian's help documents only %20. If your vault lives in Obsidian and you rename notes often, rename one test note before converting the rest.

VS Code. The behaviour sits in the source of its built-in Markdown extension. A function named needsBracketLink decides, and its comment says why: "// Links with whitespace or control characters must be enclosed in brackets"9 The path is inserted as written — relative to the open file and not percent-encoded — and wrapped in < and >.

GitHub. Its renderer accepted both forms. Its formatting guide does not settle the choice: the Relative links section, read on 2026-11-07, does not mention spaces at all.10


Three fixes that look right and are not

A backslash before the space, a plus sign in place of it, and a bare-space reference definition all look like reasonable fixes. None is portable. The backslash prints as text in six of nine settings, the plus sign links to a different file in all nine, and the bare reference definition stops being a definition in seven.

The backslash. In CommonMark, "Any ASCII punctuation character may be backslash-escaped," and a space is not punctuation.11 So [d](my\ note.md) stays a backslash and a space, and the link syntax fails. pandoc's markdown reader is the exception for its own reason — its manual says "A backslash-escaped space is parsed as a nonbreaking space."12 Two other settings made a link, to the wrong file: pandoc markdown_strict wrote my\%20note.md, and Markdown.pl wrote my\ note.md.

The plus sign. The habit comes from web forms. The URL Standard's form parser says: "Replace any 0x2B (+) in name and value with 0x20 (SP)."13 That rule belongs to form-encoded query strings — the text after a ? that a form submits. In a path, + is just +. All nine settings kept it, so [g](my+note.md) points at a file literally named my+note.md.

The bare-space reference definition. Moving the path to the bottom of the note does not help.

[agenda]

[agenda]: Meeting notes.md

In seven of nine settings that last line is not a definition. It renders as an ordinary paragraph, and [agenda] stays in square brackets, unlinked. Write the definition as [agenda]: <Meeting notes.md> — a definition in eight of nine — or with %20, which worked in all nine.


Where the no-space rule came from

Original Markdown allowed it, partly. John Gruber's Markdown.pl 1.0.1, from 2004, accepts a space inside an inline link's parentheses, but not in an image or a reference definition. CommonMark applies one rule to all three: no raw space in any destination unless the path sits in angle brackets.

The 2004 source shows the split. The inline-link pattern is <?(.*?)>? — any characters at all. Reference definitions and inline images use <?(\S+?)>?, and \S means no whitespace.14 Our test agrees: Markdown.pl linked [a](my note.md), turned ![e](my image.png) into a link with a stray !, and printed the bare-space definition as a paragraph.

That history explains a quiet failure. A note written against an older engine — or checked only through pandoc's default reader — can hold bare-space links that always rendered. Open the same folder on GitHub and they are text.

pandoc's leniency is measured, not promised. Its manual does not describe it; on spaces, the closest it comes is that the URL in a link definition "may optionally be surrounded by angle brackets."12 Treat a bare space that happens to work as an accident of the reader.


Write the path in angle brackets: [text](<Meeting notes.md>). It works for links, images and reference definitions in every CommonMark renderer we tested, and the note's name stays searchable. Use %20 — plus %28 and %29 for parentheses — only if a very old Markdown engine must read the file. Or name files without spaces.

The forms, one per line:

[agenda](<Meeting notes.md>)
![chart](<attachments/Meeting notes.png>)
[actions](<Meeting notes.md#action-items>)

[agenda-ref]: <Meeting notes.md>

[old-engine](Meeting%20notes%20%282026%29.md)

To find bare-space links already in a folder, this pattern flags (path with space.ext) and [label]: path with space.ext while skipping paths already in angle brackets:

grep -rnE --include='*.md' \
  '\]\([^<)"]* [^"]*\.[A-Za-z0-9]+\)|^\[[^]]+\]: [^<"]* [^"]*\.[A-Za-z0-9]+$' .

It is a finder, not a parser. It misses paths without a file extension and links with a quoted title, and can over-match a line holding two links, so read each hit before you change it.

If you control the names, the simpler fix is upstream: name your note files without spaces and the question never comes up. This piece is for the folder whose app already put the spaces there.


Trade-offs and what this test does not show

This is one day's run of named versions. The counts hold for GitHub's renderer as served on 2026-11-07, markdown-it 15.0.3, commonmark.js 0.31.2, marked 18.1.3, pandoc 3.13 and Markdown.pl 1.0.1. Four things sit outside the test: two hosted renderers, Obsidian itself, the click, and other awkward characters.

GitLab and Bitbucket were not tested. Two of the five Stack Exchange questions name them; neither could be reached without signing in for this test. Both forms are standard CommonMark, but their rows are not in the table.

Obsidian was read, not run. Its row comes from its help page and from dated user reports. How current Obsidian handles angle-bracket links on rename and in backlinks is untested here.

HTML, not clicks. The test checked the HTML each renderer wrote. Whether every viewer then opens the local file was not tested; the browser step is from the URL Standard, not from a measurement.

Angle brackets have edges of their own. A path containing < or > needs those escaped — VS Code inserts a backslash before each one.9 Those characters are rare in note names.


Frequently Asked Questions

How do I add a hyperlink with spaces in it using markdown?

Wrap the destination in angle brackets — [text](<my note.md>) — or replace each space with %20: [text](my%20note.md). CommonMark ends a link's destination at the first raw space, so [text](my note.md) prints as plain text on GitHub and most modern renderers. Both fixes worked in all nine settings we tested.32

How to link to a file with spaces in the filename in GitHub README.md?

Use [Setup guide](<docs/Setup guide.md>) or [Setup guide](docs/Setup%20guide.md). On 2026-11-07 GitHub's renderer turned both into a link to docs/Setup%20guide.md and printed the bare-space version as literal text. GitHub's formatting guide does not mention spaces in relative links, so the CommonMark rule is the one that applies.210

How to escape spaces in filename when including image in markdown?

The same two ways as a link: ![chart](<images/Q3 chart.png>) or ![chart](images/Q3%20chart.png). A backslash does not escape a space — CommonMark only escapes punctuation. A bare-space image rendered as an image in just two of nine settings; the angle-bracket image worked in eight, failing only in the 2004 Markdown.pl.211

Can I use a backslash or a plus sign instead of %20?

No. A backslash before a space printed as text in six of nine settings and pointed at the wrong file in two more. A plus sign means a space only in form-encoded query strings, not in paths. All nine settings linked my+note.md to a file with a literal plus in its name.213

Why does my Markdown link work in pandoc but not on GitHub?

pandoc's default markdown reader and its markdown_strict reader accept a bare space in a link path; GitHub, and pandoc's own gfm and commonmark readers, do not. The leniency is undocumented behaviour. Write the path in angle brackets or with %20 and the link renders in both.212

Do angle-bracket links work in Obsidian?

A user reported in February 2026 that Obsidian opens them, and a forum moderator noted in January 2026 that angle brackets in links are part of the CommonMark spec. Obsidian's help documents only %20, and a user reported in 2023 that renames mangled angle-bracket links. We did not test the current version — check one rename first.67158

How do I write a reference-style link to a file with spaces?

Put the path in angle brackets in the definition: [agenda]: <Meeting notes.md>, then use [agenda] in the text. Without the brackets, [agenda]: Meeting notes.md was not a definition in seven of nine settings — it rendered as a paragraph. A %20 definition worked in all nine.2


The file system lets a name have spaces. The link has to be told where the name ends.


MNMNOTE keeps your notes as open Markdown files on your own device, so every link you write is plain text another app can read. mnmnote.com


References


Footnotes

  1. Stack Exchange, view counts read via the Stack Exchange API on 2026-11-07: Super User, "How do I add a hyperlink with spaces in it using markdown?" (question 1170654, asked 2017-01-23), 41,884 views; Stack Overflow, "Link to filenames with spaces in Bitbucket Markdown" (34569256, asked 2016-01-02), 25,526; "how to link to a file with spaces in the filename in github README.md" (47050129), 16,735; GitLab broken-image question 71842465, 4,099; "How to escape spaces in filename when including image in markdown?" (62828966), 2,097. https://superuser.com/questions/1170654 ↩

  2. MNMNOTE, link-destination test run, 2026-11-07: GitHub's POST /markdown renderer (mode=gfm), markdown-it 15.0.3, commonmark.js 0.31.2, marked 18.1.3, pandoc 3.13 (markdown, gfm, commonmark and markdown_strict readers) and Markdown.pl 1.0.1; search with grep (ugrep 7.8.4) and ripgrep 15.1.0. The inputs are reproduced in this post. https://github.com/jgm/pandoc/releases/tag/3.13 ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8 ↩9

  3. MacFarlane, J., ed., CommonMark Spec, version 0.31.2 (2024-01-28), §6.3 "Links," Examples 488 and 489. Accessed 2026-11-07. https://spec.commonmark.org/0.31.2/#links ↩ ↩2

  4. MacFarlane, J., ed., CommonMark Spec, version 0.31.2, §6.5 "Autolinks." Accessed 2026-11-07. https://spec.commonmark.org/0.31.2/#autolinks ↩

  5. WHATWG, URL Living Standard, §1.3 "Percent-encoded bytes" (query and path percent-encode sets). Accessed 2026-11-07. https://url.spec.whatwg.org/#path-percent-encode-set ↩

  6. Obsidian Help, "Internal links." Accessed 2026-11-07. https://help.obsidian.md/links ↩ ↩2

  7. Obsidian Forum, "How to use spaces in markdown links," post by hannesd, 2026-02-22. https://forum.obsidian.md/t/how-to-use-spaces-in-markdown-links/111489 ↩ ↩2

  8. Obsidian Forum, "Support Internal links with markdown angle bracket syntax (especially rename)," thread opened 2021-06-11; post by idea.list, 2023-10-14. https://forum.obsidian.md/t/support-internal-links-with-markdown-angle-bracket-syntax-especially-rename/36007 ↩ ↩2

  9. Microsoft, Visual Studio Code, extensions/markdown-language-features/src/languageFeatures/copyFiles/shared.ts, functions escapeMarkdownLinkPath and needsBracketLink, commit beab7a2 (2026-08-07). https://github.com/microsoft/vscode/blob/beab7a2a9d5d7449718c6b8f4f54e1a11c4c5cb3/extensions/markdown-language-features/src/languageFeatures/copyFiles/shared.ts#L296-L311 ↩ ↩2

  10. GitHub Docs, "Basic writing and formatting syntax," section "Relative links." Accessed 2026-11-07. https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax#relative-links ↩ ↩2

  11. MacFarlane, J., ed., CommonMark Spec, version 0.31.2, §2.4 "Backslash escapes." Accessed 2026-11-07. https://spec.commonmark.org/0.31.2/#backslash-escapes ↩ ↩2

  12. MacFarlane, J., Pandoc User's Guide, "Extension: all_symbols_escapable" and "Reference links." Accessed 2026-11-07. https://pandoc.org/MANUAL.html#extension-all_symbols_escapable ↩ ↩2 ↩3

  13. WHATWG, URL Living Standard, §5.1 "application/x-www-form-urlencoded parsing." Accessed 2026-11-07. https://url.spec.whatwg.org/#urlencoded-parsing ↩ ↩2

  14. Gruber, J., Markdown.pl version 1.0.1 (2004), lines 288, 577 and 679 of the distributed script. https://daringfireball.net/projects/markdown/ ↩

  15. Obsidian Forum, "What is the status of meaning of angle brackets in link targets?", reply by moderator WhiteNoise, 2026-01-01: "The angle brackets on links are part of the CommonMark spec." Accessed 2026-11-07. https://forum.obsidian.md/t/what-is-the-status-of-meaning-of-angle-brackets-in-link-targets/109497 ↩