Minimal, privacy-focused web analytics. Self-hosted, no cookies, no tracking IDs.
# Install
uv tool install tiny-analytics
# Configure (create a .env file or set environment variables)
export TINY_ANALYTICS_PASSWORD="your-secret-password"
export TINY_ANALYTICS_SECRET_KEY="$(openssl rand -hex 32)"
# Run
tiny-analyticsAdd this to your site:
<script src="https://your-analytics-domain/snippet.js" defer></script>That's it. View your dashboard at http://localhost:8000/.
uvx tiny-analyticsgit clone https://github.com/zevaverbach/tiny-analytics.git
cd tiny-analytics
uv sync
uv run tiny-analyticsUsing pip instead of uv
pip install tiny-analytics
tiny-analyticsOr from source:
git clone https://github.com/zevaverbach/tiny-analytics.git
cd tiny-analytics
python -m venv .venv && source .venv/bin/activate
pip install -e .
tiny-analytics- Privacy-first: No cookies, no fingerprinting, no personal data stored
- Lightweight: Single Python file + templates
- Bot filtering: Automatic detection and separation of bot traffic
- Time on page: Tracks actual engagement, not just page loads
- Geo & device breakdown: See where your visitors come from and what they use
- Dark mode UI: Easy on the eyes
- Visitor hits your page → snippet.js fires a POST to
/t - Server hashes IP+UA → creates anonymous visitor ID (never stored raw)
- On page leave → beacon sends time-on-page to
/d - Dashboard → aggregates and visualizes the data
No cookies. No localStorage. No tracking across sites.
| Variable | Default | Description |
|---|---|---|
TINY_ANALYTICS_PASSWORD |
changeme |
Dashboard login password |
TINY_ANALYTICS_SECRET_KEY |
change-this... |
Session signing key (generate a random string) |
TINY_ANALYTICS_ALLOWED_ORIGINS |
[] |
Restrict tracking to specific domains (empty = allow all) |
TINY_ANALYTICS_DB_PATH |
./tiny_analytics.db |
SQLite database location |
TINY_ANALYTICS_HOST |
0.0.0.0 |
Host to bind to |
TINY_ANALYTICS_PORT |
8000 |
Port to listen on |
[Unit]
Description=tiny-analytics
After=network.target
[Service]
User=www-data
WorkingDirectory=/opt/tiny-analytics
Environment="TINY_ANALYTICS_PASSWORD=your-password"
Environment="TINY_ANALYTICS_SECRET_KEY=your-secret-key"
ExecStart=/usr/local/bin/tiny-analytics
Restart=always
[Install]
WantedBy=multi-user.targetlocation / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}tiny-analytics reads cf-connecting-ip and cf-ipcountry headers automatically for accurate geo and IP data behind Cloudflare.
tiny-analytics [OPTIONS]
Options:
--host TEXT Host to bind to [default: 0.0.0.0]
--port INTEGER Port to listen on [default: 8000]
--help Show this message and exit
| Endpoint | Method | Description |
|---|---|---|
/t |
POST | Record a pageview |
/d |
POST | Update time-on-page |
/snippet.js |
GET | Tracking script |
/ |
GET | Dashboard (auth required) |
/logs |
GET | Raw logs view (auth required) |
MIT


