Self-hosted URL shortener with click analytics, smart expiry, and QR codes. The free, open-source alternative to bit.ly and tinyurl.
What does this do? Paste a long URL, get a short one. Share it anywhere. Track who clicked — browser, OS, device, referer. Set links to auto-expire after time or clicks. Generate QR codes instantly. All data stays on your machine. No accounts, no cloud, no subscriptions.
Self-hosted by design. Clip runs on your own machine. It is NOT a public SaaS. There is no auth and no multi-user isolation — because it is intended to run locally or behind your own firewall.
- One command deploy —
docker run clipand you're running - Custom slugs — Use your own short code or auto-generate one
- Smart expiry — Choose permanent, time-based, or click-based expiration
- QR codes — Generate QR codes for any short link instantly
- Click analytics — Browser, OS, device, referer, timestamp
- Real-time dashboard — Dark mode UI to create and manage links
- Auto-cleanup — TTL-based link expiry (default 30 days)
- Zero dependencies — just SQLite, no Redis/Postgres needed
docker run -p 8080:8080 clipOpen http://localhost:8080 and start shortening URLs.
docker compose up -dgit clone https://github.com/rinopatrick/clip.git
cd clip
uv sync
uv run python -m clipPermanent (default):
curl -X POST http://localhost:8080/api/links \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com/very/long/path", "slug": "mylink"}'Time-based expiry (24 hours):
curl -X POST http://localhost:8080/api/links \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com",
"expiry_type": "time",
"expiry_hours": 24
}'Click-based expiry (max 5 clicks):
curl -X POST http://localhost:8080/api/links \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com",
"expiry_type": "clicks",
"max_clicks": 5
}'Response:
{
"id": 1,
"slug": "mylink",
"url": "https://example.com/very/long/path",
"short_url": "http://localhost:8080/mylink",
"clicks": 0,
"expiry_type": "permanent",
"is_expired": false
}curl http://localhost:8080/api/linkscurl http://localhost:8080/api/links/mylink/clickscurl http://localhost:8080/api/links/mylink/qrResponse:
{
"slug": "mylink",
"qr_url": "https://chart.googleapis.com/chart?cht=qr&chs=300x300&...",
"short_url": "http://localhost:8080/mylink"
}curl -X DELETE http://localhost:8080/api/links/mylinkcurl -v http://localhost:8080/mylink| Method | Path | Description |
|---|---|---|
| POST | /api/links |
Create a shortened link |
| GET | /api/links |
List all links (paginated) |
| GET | /api/links/{slug} |
Get link details |
| DELETE | /api/links/{slug} |
Delete a link |
| GET | /api/links/{slug}/clicks |
Get click analytics |
| GET | /api/links/{slug}/qr |
Get QR code image URL |
| GET | /{slug} |
Redirect to original URL |
| GET | /health |
Service health check |
All settings are configurable via environment variables with the CLIP_ prefix:
| Variable | Default | Description |
|---|---|---|
CLIP_HOST |
0.0.0.0 |
Server bind address |
CLIP_PORT |
8080 |
Server bind port |
CLIP_DEBUG |
false |
Enable debug mode |
CLIP_DATABASE_URL |
sqlite+aiosqlite:///./clip.db |
SQLite database URL |
CLIP_BASE_URL |
http://localhost:8080 |
Base URL for short links |
CLIP_REQUEST_TTL_DAYS |
30 |
Days before links auto-delete |
CLIP_CLEANUP_INTERVAL_SECONDS |
3600 |
Background cleanup interval |
CLIP_MAX_SLUG_LENGTH |
32 |
Max custom slug length |
- Backend: Python 3.13 + FastAPI + SQLite (aiosqlite)
- Frontend: Vanilla JS + Tailwind CSS
- Docker: Multi-stage build (slim runtime)
- Testing: pytest + pytest-asyncio + httpx
# Run tests
uv run pytest
# Lint
uv run ruff check src/If this tool saves you time, consider giving it a ⭐ on GitHub and supporting its development:
| Platform | Link | Payment Methods |
|---|---|---|
| Saweria (Indonesia) | saweria.co/rinopatrick | QRIS, GoPay, OVO, Dana, LinkAja |
| Ko-fi (International) | ko-fi.com/rinopatrick | PayPal, Credit Card |
Every cup of coffee helps keep this project alive and growing.
MIT
Clip — Shorten URLs without leaving your machine.
Current state: engineering sample / pre-production.
Recommended next steps:
- Add CI checks (tests + lint) on every push/PR
- Add release/versioning policy
- Add deployment/runtime hardening docs
- Add monitoring and operational runbook