Markdown links look simple: put the visible text in square brackets and the destination in parentheses. Real documents quickly need more than the basic form, however. Links may point to websites, another file, a heading on the same page, or an image stored beside the document. This guide covers the useful forms and the mistakes that make otherwise valid links stop rendering.
The standard syntax is:
[Visible link text](https://example.com)
The result is a clickable phrase rather than a visible URL. You can add an optional title, which some browsers show as a tooltip:
[Project documentation](https://example.com/docs "Open the documentation")
Use descriptive link text. “Read the deployment guide” tells readers where a link goes; “click here” does not. Descriptive text also makes a page easier to scan with assistive technology.
Here is the quick Markdown link syntax reference:
| Link type | Markdown |
|---|---|
| Web page | [Documentation](https://example.com/docs) |
| Another file | [Setup](./setup.md) |
| Heading on this page | [Troubleshooting](#troubleshooting) |
| Image |  |
| Visible URL | <https://example.com> |
The same bracket-and-parenthesis form works in .md files, README files, issue descriptions, and most CommonMark-based renderers. What changes between environments is how relative paths and generated heading anchors are resolved.
Documentation repositories commonly use relative paths:
[Installation guide](./guides/installation.md)
[Contributing](../CONTRIBUTING.md)
./ starts in the current file's directory. ../ moves up one directory. These links are portable while the repository structure remains intact, but they can break when a single Markdown file is copied into an online viewer without the surrounding files.
Use an absolute HTTPS URL when the destination should work independently of the repository:
[Published installation guide](https://docs.example.com/installation)
An anchor link jumps to a section on the rendered page:
[Skip to troubleshooting](#troubleshooting)
## Troubleshooting
Renderers normally turn headings into lowercase IDs, replace spaces with hyphens, and remove some punctuation. Exact rules vary. A link such as #api-reference is usually safe for a heading named “API Reference,” but duplicate headings and punctuation-heavy titles deserve testing in the final renderer.
For a heading in another file, combine a path and fragment:
[Authentication errors](./api.md#authentication-errors)
Duplicate headings are a common source of broken anchors. A renderer may generate #examples for the first heading and #examples-1 for the second, but the suffix convention is not universal. Give important link targets unique heading text and verify the generated ID in the destination renderer.
Punctuation and Unicode also vary across platforms. A heading such as “What's New in v2.0?” may lose apostrophes and punctuation when converted to an ID. GitHub, documentation generators, and CommonMark-based viewers can produce different fragments from the same heading; avoid guessing when the link must work across all of them.
A raw space can terminate a Markdown destination. For URLs containing spaces, encode them as %20 or enclose the destination in angle brackets:
[Release notes](<https://example.com/releases/Version 2.md>)
Balanced parentheses are accepted by CommonMark, but complicated URLs are easier to maintain when percent-encoded. If a link renders partly as plain text, inspect spaces and parentheses before changing the brackets.
Angle brackets are especially useful for a CommonMark link destination containing spaces:
[Design notes](<./Design Notes.md>)
They delimit the complete destination; they do not make a missing local file available after upload. For web URLs, percent-encoding spaces remains the more interoperable choice.
Long destinations can make prose difficult to edit. Reference-style links move URLs out of the sentence:
Read the [API guide][api] and [security policy][security].
[api]: https://example.com/api
[security]: https://example.com/security "Security policy"
This is particularly useful when one destination appears several times. Reference labels are matched case-insensitively by CommonMark, but consistent lowercase labels are easier to maintain.
You can also use a compact form when the visible text and reference label match:
Read the [contributing guide].
[contributing guide]: https://example.com/contributing
An image uses the same destination rules with an exclamation mark before the opening bracket:

Text inside the brackets becomes the image description and normally maps to HTML alt text. Describe the information conveyed by the image rather than writing “image” or repeating the filename.
A local image path is valid Markdown:

It will only render when the viewer can also reach that file relative to the Markdown document. Uploading or sharing the .md file alone does not automatically include its image folder.
Angle brackets create explicit autolinks in CommonMark:
<https://example.com>
<team@example.com>
Some Markdown flavors automatically link bare URLs, but explicit syntax is more portable. Use a normal descriptive link for polished documentation and an autolink when displaying the destination itself is useful.
An empty label is technically parseable in some forms but produces an inaccessible or invisible link:
[](https://example.com)
Always provide meaningful link text. If the URL itself should be visible, use an autolink such as <https://example.com> rather than empty brackets.
When a Markdown link does not work:
Paste the document into mdview.io to inspect the rendered links alongside the rest of the Markdown. Link syntax defines the destination, but the final location determines whether that destination can actually be reached.
For a deeper explanation of assets and repository paths, see how local Markdown files handle images and relative links. If only heading links fail after moving between platforms, use the cross-renderer heading-anchor guide.
Link to the heading's generated fragment, such as [Troubleshooting](#troubleshooting). Test punctuation, duplicate headings, and non-ASCII text in the final renderer.
Use a relative destination such as [Setup](./docs/setup.md). The path is resolved from the current Markdown file and only works while the destination remains available at that location.
Heading-ID generation is platform behavior rather than core Markdown link syntax. Different renderers can normalize punctuation, Unicode, and duplicate headings differently.