Media performance

# Four ways to add images to a GitHub README, plus badges

Add images to a GitHub README with repository files, issue attachments, raw URLs, HTML, or generated assets.

Published August 11, 2026

## Key takeaways

* Relative repository paths keep documentation and its assets versioned together.
* Issue-upload URLs are convenient but less obvious to audit and migrate.
* External URLs reduce repository size but introduce another availability and privacy dependency.

README images can live in the repository, use a GitHub attachment URL, reference public storage, or use HTML for limited layout control. The best option depends on ownership, versioning, portability, and update frequency.

## In this guide

1. [Choose an image location based on ownership and lifetime](#images-in-github-readmes-section-1)
2. [Keep release-specific media in the repository](#images-in-github-readmes-section-2)
3. [Treat attachments and remote images as external dependencies](#images-in-github-readmes-section-3)
4. [Use Markdown for meaning and HTML only for needed layout control](#images-in-github-readmes-section-4)
5. [Prepare images for the size at which people read them](#images-in-github-readmes-section-5)
6. [Write alternative text for the image's role](#images-in-github-readmes-section-6)
7. [Make artwork survive themes and missing resources](#images-in-github-readmes-section-7)
8. [Use badges as summaries, not as the source of truth](#images-in-github-readmes-section-8)
9. [Review images as part of documentation testing](#images-in-github-readmes-section-9)

## What matters most

* HTML image markup can set dimensions, though GitHub sanitizes unsupported elements and attributes.
* Generated status badges are useful when their service and fallback behavior are understood.

## Choose an image location based on ownership and lifetime

A README image is a documentation dependency. Before choosing a URL, decide who owns the file, whether it must change with the code, how long it should remain available, and where the README will be rendered. A versioned architecture diagram has different requirements from a temporary pull request screenshot or a badge generated from live project data.

For example, keep installation screenshots beside the README when each release documents a different interface. A community logo shared across many repositories may belong in centrally managed public storage instead. Avoid choosing a location solely because it is convenient during editing. Moving images later can break old tags, package pages, forks, and links to historical documentation.

### Repository file

Best for assets that should be reviewed, versioned, and released with the documentation.

### GitHub attachment

Convenient for discussions and occasional README media, but its ownership and migration path are less visible than a tracked file.

### External URL

Useful for centrally maintained or frequently changing assets, with an added availability, privacy, and access-control dependency.

### Generated image

Appropriate for nonessential status information when readers can still understand the project if the generator is unavailable.

## Keep release-specific media in the repository

For a tracked asset, place the file in a predictable directory such as `docs/images/` and reference it with Markdown like `![Settings screen](docs/images/settings.png)`. Relative paths make the README and image move together across branches and forks. Resolve the path from the Markdown file's location, not from the repository root, because a README inside a subdirectory has a different base path.

Treat path spelling as code. Case differences may work on one developer's filesystem but fail elsewhere. Renaming a directory, squashing an image, or deleting an apparently unused file can also break older documents. Review image changes with the text that depends on them, and use descriptive filenames rather than opaque names copied from a screenshot utility.

Pin documentation images to a stable revision when the page describes a released interface or behavior. A branch-relative path is convenient while editing, but the same README can show different artwork after the branch changes. Release notes, security advisories, and versioned setup instructions benefit from immutable references because readers can then see the image that belonged to that exact version rather than the newest replacement.

### Relative path

Usually the most maintainable reference for an image committed alongside the README.

### Default-branch URL

Always follows that branch, which is useful for current documentation but can make old references display newer artwork.

### Commit-pinned URL

Provides an immutable view for releases or audits, but requires deliberate updates when the image changes.

## Treat attachments and remote images as external dependencies

Dragging an image into a GitHub editor can produce a hosted attachment URL. That is fast and avoids adding binary data to the repository, but the resulting asset is not represented by a normal file in Git history. Record why the URL exists, keep the original somewhere controlled, and verify that repository transfers or documentation migrations will not leave the team without a manageable source.

A remote URL can reduce repository size and let one asset update across multiple documents. It can also fail because of an expired signed URL, changed access policy, deleted object, DNS problem, or hotlink restriction. Use an HTTPS location intended for durable public access, confirm that redistribution is permitted, and avoid embedding private endpoints. On github.com, rendered Markdown images are fetched through GitHub’s anonymizing Camo proxy, which hides reader network and browser details from the host, cannot fetch images that require authentication or a private network, and can keep serving a cached copy after the source changes. Renderers that do not proxy images may still disclose reader information to the host, so privacy-sensitive projects should minimize unnecessary third-party resources.

## Use Markdown for meaning and HTML only for needed layout control

Standard Markdown is the portable default: `![alternative text](path-or-url)`. It expresses the image's purpose and works across more repository browsers, package registries, documentation generators, and local preview tools. Keep optional hover titles secondary because keyboard and touch users may never receive them, and because a title does not replace alternative text or a visible explanation.

An HTML `img` element can set dimensions when a screenshot otherwise dominates the page. GitHub sanitizes unsupported HTML, attributes, and styles, so elaborate positioning may disappear or behave differently from a local preview. Prefer a simple element with `src`, `alt`, `width`, and `height`. Base64 data URLs make Markdown large, difficult to review, and poorly portable; they also prevent normal file caching and should not be the routine answer to asset management.

Prefer concise Markdown for a content image

```
![Diagram showing the request flow from the browser through the API to object storage](docs/request-flow.png)
```

Use HTML only when README layout needs it

```
<p align="center">
  <img
    src="docs/dashboard.png"
    alt="Dashboard showing three completed uploads"
    width="720"
  />
</p>
```

## Prepare images for the size at which people read them

Do not commit a full-resolution desktop capture when the README displays it in a narrow content column. Resize close to the useful reading width, while retaining enough pixel density for sharp text on high-density screens. Compression should remove waste without turning interface labels into artifacts. Compare the optimized result at its rendered size rather than judging only the file-size number.

Choose the format from the content. JPEG suits photographic images that do not need transparency. PNG remains useful for crisp interface captures, limited-color diagrams, and transparency, although it can become large. WebP can work for mixed imagery when every intended renderer is tested. SVG is effective for diagrams and logos created as vectors, but only trusted SVG should be published. Keep an editable source for diagrams even when the README uses an exported raster version.

### Crop first

Remove browser chrome, empty margins, and unrelated application areas before resizing.

### Preserve legibility

Check small labels, terminal text, and thin diagram lines at the final display width.

### Remove sensitive metadata

Inspect filenames, embedded metadata, visible account details, access tokens, and notifications before committing.

### Control repository growth

Replacing a large binary does not remove its earlier versions from Git history, so optimize before the first commit.

## Write alternative text for the image's role

Alternative text should convey what a reader needs from the image in this context. For a successful test screenshot, describe the relevant success state rather than listing every visible control. For a diagram, summarize the relationship it illustrates and explain complex details in nearby prose. Do not repeat a caption word for word or use a filename such as `screen-final-2.png` as the description.

A linked image needs text that communicates the link's destination or action, not merely its appearance. Decorative separators and repeated brand marks should have empty alternative text when the renderer permits it, while status badges should receive concise labels such as `Build: passing`. Essential commands, configuration, or error messages must also appear as selectable text because images cannot provide a reliable copy, search, translation, or zoom experience.

## Make artwork survive themes and missing resources

Transparent logos and diagrams often assume a white canvas. On a dark theme, black strokes can disappear; on a light theme, white labels can vanish. Test both themes and add an intentional background or border when one asset can serve both. If the renderer supports theme-specific picture sources, keep the light and dark versions semantically equivalent and give the overall image one useful alternative description.

Design the surrounding paragraph so the README remains understandable while an image is loading or unavailable. Never put the only installation step, security warning, or compatibility requirement inside a screenshot. Avoid meaning conveyed only by color, and check diagrams at increased zoom. These practices support accessibility while also making documentation more resilient in text-only tools, cached package pages, and restricted networks.

## Use badges as summaries, not as the source of truth

A badge is a remotely generated image that summarizes changing data such as a build result, package version, or coverage state. Its accuracy depends on the upstream service, query parameters, branch selection, authentication, caching, and refresh behavior. Link the badge to a page where readers can inspect the underlying result, and label it so the meaning is clear without decoding color.

Keep the badge row selective. A long sequence of service calls slows rendering, creates visual noise, and increases the number of parties contacted when someone opens the README. Never use a badge as the only notice of a security issue or supported version. If a provider fails, the project description and normal contributor workflow should still make sense.

## Review images as part of documentation testing

Preview the README in GitHub's renderer after committing to a branch. Open every image, verify relative paths from the actual README location, switch color themes, and inspect narrow and zoomed layouts. When the README is published to a package registry or documentation site, test that surface too because relative URL rules and supported HTML can differ.

Add lightweight operational checks for important assets. A link checker can detect missing remote images, while repository review can catch oversized binaries and untracked source files. Revisit screenshots when the interface changes, and remove obsolete assets only after searching all branches of maintained documentation. The goal is not merely a rendered image today, but an understandable document throughout the project's supported lifetime.

### Rendering

Verify the repository page, forks, release tags, package mirrors, and any generated documentation that consumes the README.

### Accessibility

Review alternative text, text contrast, theme behavior, zoom, and whether essential information is available outside images.

### Performance

Check encoded dimensions, transfer size, badge count, and whether multiple full-resolution screenshots are necessary.

### Governance

Confirm ownership, license, editable source, update responsibility, and a migration plan for externally hosted assets.

## Technical details worth knowing

* Relative image URLs are resolved differently on a repository page, package registry, copied Markdown file, and external documentation renderer, so portability should be tested.
* Alternative text should communicate the image’s purpose without repeating the nearby caption; status badges can use concise labels such as “Build: passing” instead of verbose filenames.
* Badges are remotely generated images whose availability, caching, privacy, and accuracy depend on another service, making them unsuitable for essential project information.
* Repository-hosted images are versioned with the project, but links to a branch can change while links to a commit are immutable and harder to maintain.
* Large screenshots slow repository pages and clones when committed directly, so dimensions, compression, update frequency, and storage location should be considered.
* Dark and light GitHub themes can make transparent logos or diagrams unreadable; picture source media queries can provide theme-specific artwork where supported.

## A practical approach

1. 1\
   Choose asset ownership and lifetime before selecting the Markdown URL.
2. 2\
   Resize screenshots to their useful reading width and optimize without blurring text.
3. 3\
   Write concise alt text and use a descriptive filename.
4. 4\
   Preview the README in GitHub’s renderer and verify links from forks and package mirrors.

A four-stage media workflow

## Architecture boundary

GitHub controls README rendering and repository permissions. Image-processing tools can prepare files before they are committed or linked, but they do not upload into Git history or manage GitHub attachments.

## Frequently asked questions

### Should README images use relative or absolute URLs?

Use relative paths for files versioned with the repository because they normally follow branches and forks. Use an absolute HTTPS URL when another system intentionally owns the asset. Test either form in every important renderer, since package sites and copied Markdown may resolve paths differently.

### Can a README image be resized with Markdown?

Basic Markdown does not provide a portable sizing syntax. Use a simple HTML `img` element with `width` and `height` when sizing is necessary, then preview it on GitHub. Optimize the source file as well, because display dimensions do not reduce downloaded bytes.

### Is embedding an image as base64 a good way to avoid broken links?

Usually not. Base64 makes the README harder to read and review, increases its text size, reduces caching flexibility, and may be rejected by some renderers. A tracked image file or deliberately managed public URL is easier to maintain.

### Are externally hosted README images safe for private repositories?

Do not assume so. GitHub fetches and caches rendered images through its anonymizing proxy, so images that need cookies or a private network will not display, other renderers may let readers contact the host directly, and a public URL can expose an asset independently of repository permissions. Avoid confidential content, use an approved host, and understand GitHub's current image handling before embedding third-party resources.

### How should screenshots containing account data be handled?

Capture a dedicated test account when possible. Crop unrelated areas, redact tokens and personal information, inspect notifications and browser chrome, and remove sensitive metadata. Cover sensitive text with opaque blocks rather than blur or pixelation, because obscured characters can sometimes be reconstructed from the published pixels, and underlying details can also remain in source files or editing history.

Media performance

## Continue with related guides

* [Five best practices for HTML and CSS background images](/guides/html-background-image-best-practices.md)\
  Five practices for CSS background images that balance composition, accessibility, and page performance.
* [Five ways to use images in React, from static imports to user uploads](/guides/import-images-in-react.md)\
  Compare static imports, public paths, remote URLs, CSS imports, and runtime upload results in React.
* [Six reliable ways to save images in Python](/guides/save-images-in-python.md)\
  Save images from bytes, URLs, Pillow, OpenCV, uploads, and managed processing results without losing error handling.
* [Eight image SEO optimization practices](/guides/image-seo-optimization.md)\
  Eight image SEO practices covering semantics, dimensions, formats, performance, discovery, and measurement.
* [How to serve responsive images from one URL](/guides/serve-responsive-images-from-one-url.md)\
  Derive every image size from one canonical URL, cache the results at the edge, and keep the encoding bill flat while traffic grows.
