Skip to main content

badgepy

CI codecov pypi versions

badgepy is a Python library and command-line tool for generating GitHub-style badges as SVG images — no external service required. Badges are rendered locally, offline, and fully under your control. It also provides a local shields.io-style badge generator — generate badges from CI reports (JUnit, Cobertura), use preset recipes for build/coverage/version/license badges, and serve them via a Flask server, all without relying on external services.

The visual design follows the Shields specification and is compatible with Shields.io.

Shields.io vs badgepy

Both tools produce identical-looking badges, but they work very differently. Here's how to choose:

Shields.io badgepy
How it works HTTP service — you request a badge URL and get back an SVG Python library/CLI — generates SVGs locally
Internet required Yes (or self-host) No — works fully offline
Setup Zero — just use a URL in your README pip install badgepy
Customization URL query parameters only Full programmatic control in Python
CI integration Via shields.io endpoint JSON Native parsers for JUnit, Cobertura, generic JSON
Rate limits Yes on shields.io (no limits if self-hosted) None
Preset badges Static badge only build, coverage, version, license, custom, progress
Output Rendered in browser from URL SVG string, file, or served from your own app

Choose Shields.io if:

  • You just need a few badges in a README and don't want to install anything
  • Your badge data is already exposed via a public API
  • You're comfortable with the hosted service's availability and rate limits

Choose badgepy if:

  • You're generating badges in a CI/CD pipeline and want offline reliability
  • You need programmatic control over badge generation from Python
  • You're parsing local test/coverage reports (JUnit, Cobertura) into badges
  • You want to serve badges from your own application
  • You need zero network dependencies at badge generation time

💡 Already using Shields.io static badges? See the Shields.io Migration Guide for a drop-in replacement path.

Sponsors

Canonical

badgepy is supported by Canonical through thanks.dev. Thank you, Canonical, for supporting open source maintainers and helping make continued maintenance of badgepy possible.

If your team depends on badgepy or wants to support independent open source maintenance, please consider sponsoring the project through thanks.dev or GitHub Sponsors.

Getting Started

Installing

pip install badgepy

Verify the installation:

python -m badgepy --left-text=build --right-text=failure --right-color='#c00' --browser

You should see a badge like this in your browser:

pip installation

Usage

badgepy can be used from the command line and as a Python library.

Prefer to start with the CLI? It's a great way to experiment before writing code. Prefer to see a running server? Check out the example Flask server.

Command Line

Full documentation of all command-line arguments:

badgepy --help

A complete example demonstrating every option:

badgepy \
    --left-text=complete \
    --right-text=example \
    --left-color=green \
    --right-color='#fb3' \
    --left-link=http://www.complete.com/ \
    --right-link=http://www.example.com \
    --logo='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAIAAAD91JpzAAAAD0lEQVQI12P4zwAD/xkYAA/+Af8iHnLUAAAAAElFTkSuQmCC' \
    --embed-logo \
    --whole-title="Badge Title" \
    --left-title="Left Title" \
    --right-title="Right Title" \
    --browser

complete

Logos

The --logo option accepts a URL:

badgepy \
    --left-text="python" \
    --right-text="3.10, 3.11, 3.12, 3.13, 3.14" \
    --whole-link="https://www.python.org/" \
    --browser \
    --logo='https://dev.w3.org/SVG/tools/svgweb/samples/svg-files/python.svg'

python

Use --embed-logo to inline the logo data directly into the SVG, saving an HTTP request at render time. This is especially useful offline or in browsers that block external image references.

--embed-logo=yes --embed-logo=no

Use --logo-width for wide custom logos and --font-family when you need a specific SVG font stack:

badgepy \
    --left-text=downloads \
    --right-text=2.7G \
    --logo='data:image/svg+xml;base64,...' \
    --logo-width=28 \
    --font-family="Open Sans,sans-serif" \
    -o badges/downloads.svg

Titles

The title element is shown as a tooltip by browsers but is currently filtered by GitHub. --whole-title applies to the whole badge, while --left-title, --right-title and --center-title are shown when hovering that part.

Styles

--style selects the look of the badge, matching the shields.io styles of the same name:

Style Corners Gradient
flat (default) rounded yes
flat-square square no
badgepy --left-text=build --right-text=passing --right-color=brightgreen --style=flat-square

style-flat-square

Everything else — geometry, text, colors, logos, links and titles — is identical between the two. --style applies to the badge command; preset and CI-report badges are always flat.

Library

from badgepy import badge

s = badge(left_text='coverage', right_text='23%', right_color='red')
# s is a string containing the badge as an SVG image.
print(s[:40])  # => <svg height="20" width="191.0" xmlns="ht

Keyword arguments mirror the CLI flags, with underscores instead of hyphens (e.g. --left-text → left_text=).

Serving Badges from a Web App

badgepy can be used to serve badge images on the web. See the Flask example for a minimal setup.

Start the example server with:

nox -s serve

Then open http://127.0.0.1:5000/ to view the badges.

Preset Badges

Common badge types with automatic color coding, no manual color picking needed:

Command Preview
badgepy preset build passing -o badges/build.svg build passing
badgepy preset coverage 85.3 -o badges/coverage.svg coverage 85.3%
badgepy preset version v1.2.3 -o badges/version.svg version v1.2.3
badgepy preset license MIT -o badges/license.svg license MIT
badgepy preset custom "linux" --label platform --color green -o badges/platform.svg platform linux
badgepy preset progress 75 --label docs -o badges/docs.svg docs progress

From Python:

from badgepy.presets import build_badge, coverage_badge, custom_badge, progress_badge

svg = build_badge('passing')
svg = coverage_badge(85.3)
svg = custom_badge(label='platform', message='linux', color='green')
svg = progress_badge(75, label='docs')

CI Report Badges

Generate badges directly from test and coverage report files — no external API needed:

Command Preview
badgepy from-junit tests/test-results.xml -o badges/tests.svg tests
badgepy from-coverage tests/coverage.xml --output-dir badges/ coverage branch-coverage
# From generic key-value or JSON files
badgepy from-generic metrics.json --output-dir badges/

# From structured local JSON/TOML files
badgepy from-json package.json --query version --label npm -o badges/npm.svg
badgepy from-pyproject --query project.name --label package -o badges/package.svg
badgepy from-lock uv.lock jinja2 --label jinja2 -o badges/jinja2.svg
badgepy from-json coverage-summary.json \
    --query total.lines.pct \
    --label coverage \
    --template "{value}%" \
    --thresholds "90:brightgreen,80:green,60:yellow,0:red" \
    -o badges/coverage.svg

From Python:

from badgepy.parsers import badges_from_junit, badges_from_coverage
from badgepy.parsers.structured import badge_from_structured_data

badges = badges_from_junit('tests/test-results.xml')   # {'tests': '<svg...>'}
badges = badges_from_coverage('tests/coverage.xml')    # {'coverage': '<svg...>', 'branch-coverage': '<svg...>'}
svg = badge_from_structured_data('pyproject.toml', query='project.version', label='pypi')

See the CI Integration Guide for GitHub Actions, GitLab CI, and Jenkins examples.

Output to File

Use -o / --output to write badges to a file instead of stdout:

badgepy --left-text=build --right-text=passing --right-color=green -o badges/build.svg

Caveats

  • Text measurement: badgepy uses a pre-calculated table of text widths and kerning distances for western glyphs. Eastern European languages may not render as accurately:

    saying-russian

    Glyphs not present in Deja Vu Sans (the default font) may render poorly:

    saying-chinese

  • Right-to-left languages: Arabic, Hebrew, and other RTL scripts are not explicitly supported; the text direction may be incorrect:

    saying-arabic

Development

git clone https://github.com/shenxianpeng/badgepy.git
cd badgepy
python -m venv venv
source venv/bin/activate
pip install -e .[dev]
nox

Contributions are welcome! Please read the contributor guide before submitting a PR.

Versioning

This project follows SemVer. See the changelog for what changed in each release, including upgrade notes for major versions.

License

This project is licensed under the Apache License — see the LICENSE file for details.

Metadata

Release files for badgepy 2.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Built distribution (wheel)

Table of built distributions (wheels) for badgepy 2.0.0
File Interpreter ABI Platform
badgepy-2.0.0-py3-none-any.whl Python 3 none any Details

Release files / badgepy-2.0.0-py3-none-any.whl

Download URL badgepy-2.0.0-py3-none-any.whl
Size 78.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
0058abc6c29277f038c744d879f2125ec1e33bec5da99f82c0315331a9d1f006
BLAKE2b-256 checksum
How to use checksums
d46e0072e316be2a32244d892340808dc5e1c08f6bc8f67ef3803cd8d832c9cb
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.8

Release history Release notifications | RSS feed

This release

2.0.0 This release

1 release file

1.3.0

1 release file

1.2.1

1 release file

1.2.0

1 release file

1.1.0

1 release file

1.0.0

1 release file

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page