GIFs in GitHub READMEs: Making Developer Demos That Load Fast

June 12, 2026

A repo with a demo GIF gets the point across before anyone reads a word. A repo with a 40 MB demo GIF gets a spinner, a half-loaded page, and a visitor who’s already gone. This guide covers how to put a GIF in a GitHub README that plays instantly: the actual file size limits, the recording settings that keep things readable, and which tool to use for terminal vs. UI demos.

Why GIFs still win in READMEs

GitHub has technically supported video in READMEs since May 2021 — you can drag an MP4, MOV, or WebM into the web editor and it embeds a player. So why does almost every popular repo still use GIFs?

Three practical reasons:

  1. GIFs autoplay and loop. Videos in READMEs render as a click-to-play player with controls. A GIF starts moving the instant the page loads. For a 6-second “here’s what this tool does” demo, removing that one click matters more than it sounds.
  2. GIFs work with normal image syntax and relative paths. ![demo](docs/demo.gif) just works for a file committed to your repo. Videos don’t: relative paths and raw.githubusercontent.com URLs don’t render as embedded players — the video has to be uploaded through GitHub’s web editor, which gives you an opaque asset URL you can’t manage in version control.
  3. GIFs render everywhere markdown renders — GitHub mobile, package registries that mirror your README (npm, PyPI), and documentation generators. Video embeds are a GitHub-web-only feature.

The honest trade-off: GIF is a terrible video format. It’s capped at 256 colors per frame, has no real inter-frame compression to speak of, and routinely produces files 5–10x larger than an equivalent H.264 MP4. The whole game is working within those constraints. (If you’ve inherited an oversized GIF and want the reverse path, a GIF to MP4 conversion typically cuts the file size by 80–90%.)

GitHub’s actual size limits

Numbers people misquote constantly, straight from GitHub’s docs:

LimitSizeSource
File pushed via git (warning)50 MiBAbout large files
File pushed via git (hard block)100 MiBsame
File uploaded via web interface25 MiBsame
Image/GIF attached in issues, PRs, markdown editor10 MBAttaching files
Video attached (free plan)10 MBsame
Video attached (paid plan)100 MBsame

So yes, you can commit a 90 MB GIF via git push. You should not. Two reasons beyond politeness:

  • READMEs load through GitHub’s Camo image proxy, and a multi-megabyte GIF visibly delays the repo page. Visitors on hotel wifi see a gray box.
  • Git never forgets. Every time you re-record and commit a new version of demo.gif, the old blob stays in history forever. Five revisions of an 8 MB GIF is 40 MB added to every fresh clone, permanently.

Practical targets: keep README GIFs under 10 MB as a hard ceiling, and aim for 2–5 MB. Under 2 MB feels instant on most connections.

Where to put the file

OptionProsCons
Commit to repo (docs/ or .github/assets/)Versioned, relative paths, survives forksBloats clone size with every revision
Drag-and-drop into README via web editorZero clone bloat, GitHub-hostedOpaque URL, not versioned, 10 MB cap
Separate “assets” repo or orphan branchClean main repoMore moving parts, links break if you rename things

For a GIF you’ll rarely re-record, committing it to the repo is fine. If you iterate on demos often, the web-editor upload keeps your git history lean.

Recording settings that keep demos readable

Most bad README GIFs fail at recording time, not encoding time. The fixes:

Record at the size you’ll display. GitHub renders README content in a column roughly 700–900px wide depending on viewport. Record your terminal or app window at 640–800px wide and ship the GIF at that exact size. Downscaling a 2560px retina capture makes text fuzzy and wastes bytes encoding detail nobody sees. If you already have an oversized capture, a GIF resizer that scales to 50% will roughly quarter the file size — but native-resolution capture always looks sharper.

15 fps is plenty. Often 10–12 is. Screen content is mostly static: typing, clicks, occasional scrolls. Nobody can tell 15 fps from 30 fps in a terminal demo, but the encoder sure can — frame rate scales file size close to linearly for screen content.

Trim ruthlessly. Every second of “watch me move the mouse to the menu” is dead weight. A good demo GIF is 5–15 seconds: the command, the result, done. Cut the app launch, cut the typo corrections, cut the pause where you checked your notes. If the demo genuinely needs 45 seconds, it’s a video — embed an MP4 below the fold or link to it.

Bump the font size before recording. For terminal demos, 16–20pt minimum. The GIF will be viewed at README width on a laptop, possibly on a phone. A 12pt font that’s crisp on your monitor is soup after GIF quantization.

Pick a high-contrast theme. GIF’s 256-color palette punishes subtle gradients and low-contrast color schemes. Solid dark background, bright text, no transparency effects.

What the math looks like

Rough real-world numbers for screen-content GIFs with a decent encoder:

  • 10-second terminal demo, 640px wide, 12 fps: 1.5–3 MB
  • 10-second UI demo, 800px wide, 15 fps: 4–8 MB
  • 20-second UI demo, 1280px wide, 30 fps: 25–60 MB — over every limit that matters

If your export lands over budget, run it through a GIF compressor — lossy quantization plus frame deduplication often cuts screen recordings 40–60% with no visible change, since most frames barely differ from their neighbors.

Tools: terminal demos vs. UI demos

ToolPlatformBest forNotes
asciinema + aggLinux/macOSTerminalRecords text events, not pixels; agg renders casts to GIF via gifski
VHSLinux/macOS/WindowsTerminalScriptable .tape files — demos as code, perfect for CI-regenerated GIFs
ScreenToGifWindowsUIBuilt-in frame editor for trimming and annotations
KapmacOSUIClean capture, exports GIF and MP4
LICEcapWindows/macOSUIAncient but tiny; records straight to GIF
ffmpeg + gifskiAllConversionBest-quality GIF encoding if you live in the terminal
GIF DenBrowserConversionConverts screen recordings (MP4/WebM/MOV) to GIF locally in your browser — nothing uploads, no watermark

For terminal demos, seriously consider asciinema. It records your session as text events, so a .cast file is a few kilobytes instead of megabytes. The catch for READMEs: you can’t embed the interactive player in GitHub markdown, so the standard pattern is rendering a GIF with agg (which uses the gifski encoder for high-quality output, with control over font, theme, and playback speed) or linking a preview image to the asciinema.org recording.

VHS deserves a special mention if your demo will go stale. You write a .tape script (“type this, wait 2s, press enter”), and VHS renders the GIF deterministically. When your CLI’s output changes, you re-run one command — or regenerate in CI — instead of re-recording by hand.

For UI demos, any screen recorder that outputs MP4 works: record with your OS tool (Win+Alt+R on Windows, Cmd+Shift+5 on macOS), trim, then convert. If the footage contains anything sensitive — internal tools, customer data on screen — a converter that runs entirely client-side avoids shipping that footage to a third-party server. That’s verifiable, not a trust-me claim: here’s how to check with your browser’s network tab.

Quick extras worth knowing

  • Control display size without re-encoding: <img src="docs/demo.gif" width="600"> works in GitHub markdown. But the full file still downloads — this is cosmetic, not a performance fix.
  • Light/dark mode variants: GitHub supports <picture> with prefers-color-scheme in READMEs, so you can ship theme-matched GIFs. Doubles your asset weight, though.
  • Accessibility: a looping GIF can’t be paused, which is hostile to some users and distracting to everyone reading around it. Keep loops short and calm, and put the GIF after your one-line project description, not before it.

Checklist before you commit

  • Recorded at 640–800px wide, native resolution (no downscaling)
  • 10–15 fps
  • 5–15 seconds, dead time trimmed
  • Terminal font 16pt+, high-contrast theme
  • Final file under 10 MB, ideally 2–5 MB
  • Terminal demo? You probably want asciinema/VHS instead of pixel capture
  • Demo longer than 20 seconds? Embed an MP4 instead (10 MB cap on free plans)
  • <img width> set if the GIF shouldn’t span the full README column