A visitor count service for your Blog, Portfolio website or Github repo or issue
Find a file
Raman fa419c3ca5
Some checks failed
ci / docker (push) Has been cancelled
ci / docker-backup (push) Has been cancelled
docs: update README and landing page for bulletproof edition
- Document hybrid unique counting, admin API, backup/health check
- Fix page_id typo in options table, remove experimental label from unique flag
- Add self-hosting section with env vars and docker-compose instructions
- Add bot filtering and unique counting explanation sections
- Update "What's next?" to reflect completed items and future roadmap
- Add Admin API nav link and docs section to landing page

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 19:07:21 +05:30
.github feat: bulletproof edition — hybrid unique counting, namespace mgmt, backup sidecar, test suite 2026-03-29 19:04:20 +05:30
backup feat: bulletproof edition — hybrid unique counting, namespace mgmt, backup sidecar, test suite 2026-03-29 19:04:20 +05:30
templates docs: update README and landing page for bulletproof edition 2026-03-29 19:07:21 +05:30
tests feat: bulletproof edition — hybrid unique counting, namespace mgmt, backup sidecar, test suite 2026-03-29 19:04:20 +05:30
.dockerignore Containerized application 2022-04-14 17:07:33 +05:30
.env add dotenv support to store md5 key config 2020-04-10 23:12:22 +08:00
.gitignore Update gitignore 2020-04-10 19:43:30 +08:00
docker-compose.yml feat: bulletproof edition — hybrid unique counting, namespace mgmt, backup sidecar, test suite 2026-03-29 19:04:20 +05:30
Dockerfile Containerized application 2022-04-14 17:07:33 +05:30
LICENSE Initial commit 2020-03-27 15:09:21 +08:00
main.py feat: bulletproof edition — hybrid unique counting, namespace mgmt, backup sidecar, test suite 2026-03-29 19:04:20 +05:30
README.md docs: update README and landing page for bulletproof edition 2026-03-29 19:07:21 +05:30
requirements-dev.txt feat: bulletproof edition — hybrid unique counting, namespace mgmt, backup sidecar, test suite 2026-03-29 19:04:20 +05:30
requirements.txt feat: bulletproof edition — hybrid unique counting, namespace mgmt, backup sidecar, test suite 2026-03-29 19:04:20 +05:30
runtime.txt First commit with badge gen ok and non finished index page 2020-04-10 19:43:17 +08:00
start.sh add dotenv support to store md5 key config 2020-04-10 23:12:22 +08:00
TODOS.md feat: bulletproof edition — hybrid unique counting, namespace mgmt, backup sidecar, test suite 2026-03-29 19:04:20 +05:30

Visitor Badge

Count visitors for your GitHub, Blog or Portfolio Site in just one line markdown code or one api call

visitor badge

How to use?

If you know how to add picture in markdown or image in html, then you are good to go.

Markdown

![visitors](https://visitor-badge.example.net/badge?page_id={page.id}&left_color=red&right_color=green)

HTML

<img src="https://visitor-badge.example.net/badge?page_id={page.id}&left_color=red&right_color=green" />

API

curl -X GET "http://visitor-badge.example.net/count?page_id={page.id}"

// output: {"value": 100}

Options

Params Required Default Description
page_id Required null Unique string to best represent your page
namespace Optional default Unique key to group all your pages and avoid conflict with others (max 10 chars)
read Optional false Only return existing count, don't increment
unique Optional false Only count unique visitors within a given window as set by timeframe param. Uses cookie-based dedup with server-side fingerprint fallback for cross-origin embeds
timeframe Optional 600 Time window (in seconds) for unique visitor dedup. Range: 60-86400 (1 min to 24 hrs)
*left_color Optional #595959 Left side color of the badge
*left_text Optional visitor Left side text of the badge
*right_color Optional #1283c3 Right side color of the badge

Note: * options only applied for path /badge

Bot Filtering

Common bots (Googlebot, bingbot, crawlers, etc.) are automatically detected and excluded from visitor counts. You can customize the bot detection patterns via the BOT_UA_PATTERNS environment variable (comma-separated regex patterns).

Unique Visitor Counting

When unique=true, the service uses a two-layer dedup strategy:

  1. Cookie-based (primary): Works for direct browser visits. Requires HTTPS for cross-origin badge embeds (SameSite=None).
  2. Fingerprint-based (fallback): For cross-origin <img> embeds where cookies aren't available. Uses a hash of IP prefix + browser family + time bucket.

The /count endpoint returns a method field when unique=true indicating which dedup method was used: "cookie" or "fingerprint".

Admin API

Manage namespace-level configuration via the admin API. All endpoints require an X-API-Key header matching the ADMIN_API_KEY environment variable. Rate limited to 10 requests/minute per IP.

# List all namespace configs
curl -H "X-API-Key: YOUR_KEY" http://localhost:5000/admin/namespaces

# Get namespace config
curl -H "X-API-Key: YOUR_KEY" http://localhost:5000/admin/namespace/myns

# Set namespace badge defaults
curl -X PUT -H "X-API-Key: YOUR_KEY" -H "Content-Type: application/json" \
  -d '{"badge_defaults": {"left_color": "blue", "left_text": "hits"}}' \
  http://localhost:5000/admin/namespace/myns

# Delete namespace config
curl -X DELETE -H "X-API-Key: YOUR_KEY" http://localhost:5000/admin/namespace/myns

Namespace badge defaults are applied when a badge request includes namespace=myns. User query params still override namespace defaults.

Health Check

curl http://localhost:5000/health/backup
// output: {"status": "healthy", "last_backup": "2026-03-29T12:00:00Z"}

Returns 200 if backup ran within the last 2 hours, 503 if stale or unknown.

Self-Hosting

Docker Compose

git clone https://github.com/ramank775/visitor-badge.git
cd visitor-badge

Create a .env file:

md5_key=your_secret_key
ADMIN_API_KEY=your_admin_key
docker-compose up -d

This starts three services:

  • redis: Data store
  • visitor-badge: The badge service on port 5000
  • backup: Hourly Redis backups with 48hr hourly + 30-day daily retention

Environment Variables

Variable Required Default Description
md5_key Yes - Secret key for page ID hashing
redis_host No 127.0.0.1 Redis host
redis_port No 6379 Redis port
redis_db No 0 Redis database number
ADMIN_API_KEY No - API key for admin endpoints (disabled if not set)
BOT_UA_PATTERNS No (built-in) Comma-separated regex patterns for bot detection
host No 127.0.0.1 App listen host
port No 5000 App listen port

Backup & Restore

Backups run automatically every hour via the backup sidecar container. Snapshots are stored in the backup-data Docker volume.

To restore from a backup:

./backup/restore.sh /path/to/backups/daily/dump-20260329.rdb

Note: With Docker named volumes, you may need to use docker cp to place the RDB file into the Redis container's data directory.

Public Servers

  • URL: https://visitor-badge.one9x.com

    Free: Yes

    Please be aware that this server is hosted on a homelab environment, which may result in occasional downtime or data loss. To minimize the risk of data loss, nightly data snapshots are taken at 12:00 AM IST.

What's next?

  • Data federation: Allow independent servers to sync visitor data for shared namespaces
  • Real-time badges: Show "X people viewing now" instead of total count
  • Active viewers: Track live presence per page

Have something in mind? Just tell me...

Fork From

jwenjian: https://github.com/jwenjian/visitor-badge