GitHub Badge Generator
Design a badge, watch it render here as SVG, and copy the shields.io URL or the ready-to-paste Markdown — nothing is fetched from this page.
Badge preview — scroll sideways to see a wide badge
89 × 20 px, drawn on this device. Nothing was fetched.
Badge URL
https://img.shields.io/badge/build-passing-brightgreen

- white badge text on #4b0 is 2.51:1 — below the 4.5:1 WCAG 2.2 minimum for text this size
Do it offline:$
How to use it
- Fill in the two halves. The message on the right is required; the grey label on the left may be left empty, which gives a message-only badge. Both take up to 256 characters.
- Choose a colour by shields name — brightgreen, green, yellowgreen, yellow, orange, red, blue, grey, lightgrey, blueviolet, or the aliases success, important, critical, informational and inactive — or hex in 3, 4, 6 or 8 digits, with or without the hash. A label colour overrides the default #555 left half.
- Pick flat or flat-square. Flat rounds the corners with a 3 px clip and lays a gradient over both halves; flat-square drops both for crisp edges. A logo slug only writes logo= into the URL.
- Copy the URL, or switch the output tab to Markdown, HTML or RST and copy the line — given a link target it comes back wrapped in that format's anchor. Or download the SVG and commit it.
Type a label and a message, pick a colour and a style, and the badge is drawn here as SVG while you type. Copy the img.shields.io URL, the Markdown, HTML or reStructuredText line, or the SVG itself. Nothing is fetched: the preview is rendered on this device and the URL is assembled locally.
Examples
build · passing · brightgreen · flathttps://img.shields.io/badge/build-passing-brightgreen

89 × 20 px drawn here · 88 px served by shields.ioThe default badge, and the state a fresh permalink restores. The path form reads label-message-colour, so no query string is needed. One pixel separates the renders.
a-b · c_d e · bluehttps://img.shields.io/badge/a--b-c__d%20e-blue
aria-label="a-b: c_d e" · 68 px here and 68 px from shields.ioEach dash and each underscore doubles, because a single dash separates the fields and a single underscore means a space. This form is emitted only when decoding it returns your text.
github-workflow · facebook/react · runtime_build_and_test.yml · mainhttps://img.shields.io/github/actions/workflow/status/facebook/react/runtime_build_and_test.yml?branch=main
this URL is text — nothing on this page loads it; shields reads the live value when a reader of your README loads the imageDynamic mode composes the documented endpoint path and stops there. This endpoint wants the workflow FILE, not its display name; the branch rides in a query parameter.
</text><script>alert(1)</script>https://img.shields.io/badge/x-%3C%2Ftext%3E%3Cscript%3Ealert(1)%3C%2Fscript%3E-blue
<text x="1155" y="140" textLength="1886"></text><script>alert(1)</script></text>Markup typed into a field stays typography: in the SVG the angle brackets become character references inside one text node; in the URL they are percent-encoded.
Every example on this page is executed against the same engine that powers the tool, on every build.
Gotchas worth knowing
The dash is a separator before it is a character
Some text cannot be written in the path grammar at all: a label ending in a dash leaves the run of dashes ambiguous, and shields resolves it the other way. When decoding the segment stops returning what you typed, the URL switches to the static/v1 form.
Widths here are computed from a committed metric table
Width has to be known without a browser laying the text out, so the renderer sums advances from a table measured once in headless Chrome for the Verdana, Geneva, DejaVu Sans, sans-serif stack, then pads each half by five pixels a side. Against the thirteen logo-free rows captured from shields.io on 2026-08-13, every render lands within one pixel. CJK, emoji and combining marks raise a warning that counts them.
A logo lives in the URL, not in this preview
The logo field appends a logo= parameter that shields resolves against its own icon set; this page draws no icon, so the served badge is wider than the preview. In the captured row the difference is 17 pixels — hence the chip as soon as the field is filled.
A shields URL means your readers talk to shields
Paste one of these URLs into a README and the image is fetched by shields.io from the browser of every person who opens that page, so shields — not this tool — sees those readers. Nothing here loads any of it, at any time. To keep third parties out, download the SVG and commit it.
Common errors
`chartreuse` is not a shields colour — expected one of brightgreen, green, yellowgreen, yellow, orange, red, blue, grey, lightgrey, blueviolet (or the aliases success, important, critical, informational, inactive, gray, lightgray), or a 3/4/6/8-digit hex such as `#4b0`- CSS colour keywords are not shields colour names. On the server an unknown name silently returns a grey badge — hence the refusal here.
the message is empty — a badge needs a right-hand side; the label is the optional half- The half most people expect to be optional is the required one: clearing the label yields a valid one-colour badge, clearing the message leaves nothing to draw.
the label is 300 characters — this tool's limit is 256 characters per field- 256 characters per field is this tool's ceiling, not the format's. The count printed is the length actually submitted, so it is clear how much has to go.
`main` is not a valid workflow — this endpoint takes the workflow FILE, such as `ci.yml` or `release.yaml`- The endpoint identifies a workflow by its file name in .github/workflows, not by the name: field inside it. Every field is grammar-checked, so a badge that could only 404 is refused.
FAQ
Why is my badge a different width here than on GitHub?
Because two different renderers measured the same text: shields lays it out on its server, this page sums advances from a committed table for the Verdana, Geneva, DejaVu Sans, sans-serif stack. Without a logo the captured gap is one pixel at most; with one, 17 pixels.
How do I put a dash or a space in a badge?
Type them normally: each dash becomes two dashes, each underscore two underscores, and a space becomes %20. The doublings exist because the path form spends a single dash on separating fields and a single underscore on a space. Text that resists falls back to the query form.
Does this page contact shields.io?
No. The preview is our own SVG, the URL is string assembly, and dynamic URLs are composed as text and never opened — watch the network panel. shields.io is an independent project named here for reference; the contact happens in your readers' browsers.
Keyboard shortcuts
- ⌘/Ctrl + C
- Copy the emitted line while focus is in the tool and no text is selected; a real selection copies itself.
- ⌘/Ctrl + Shift + C
- Copy that same line even while a text selection exists.
- ⌘/Ctrl + S
- Download badge.svg — the unmodified bytes of the render, not the page.
- ? or ⌘/Ctrl + /
- Open the keyboard shortcut overlay.
- Esc
- Close the topmost dialog; every field keeps its value.