A FastAPI-based URL shortener with a built-in web UI. Shorten URLs, use custom keys, peek at targets without redirecting, and delete links via secret keys.
- Shorten URLs — generates a random 5-character key for any valid URL
- Custom keys — optionally choose your own short key instead of a random one
- Peek — check where a short URL points without being redirected
- Graceful forward — verifies the target is reachable before redirecting (returns
502if not) - Soft delete — deactivate shortened URLs via their secret key
- Web UI — single-page interface served directly by FastAPI
shortener_app/
├── __init__.py
├── config.py # Settings via pydantic-settings, supports .env
├── crud.py # Database operations
├── database.py # SQLAlchemy engine and session
├── keygen.py # Random and unique key generation
├── main.py # FastAPI app, routes, and static file serving
├── models.py # SQLAlchemy URL model
├── schemas.py # Pydantic schemas
└── static/
└── index.html # Web UI
- Python 3.10+
- uv (recommended)
git clone https://github.com/Dvdandrades/URL_Shortener.git
cd Url_short
uv syncuvicorn shortener_app.main:app --reloadThe app will be available at http://localhost:8000.
Create a .env file in the project root to override defaults:
ENV_NAME=Production
BASE_URL=https://your-domain.com
DB_URL=sqlite:///./shortener.dbCreate a shortened URL.
Body:
{
"target_url": "https://example.com",
"custom_url": "my-key"
}custom_url is optional. Allowed characters: letters, digits, . _ ~ -
Response:
{
"url": "http://localhost:8000/my-key",
"admin_url": "http://localhost:8000/admin/my-key_XXXXXXXX",
"target_url": "https://example.com",
"is_active": true,
"clicks": 0
}Redirect to the target URL. Verifies the target is reachable first.
302— redirects to target404— key not found502— target URL is unreachable
Returns the target URL without redirecting.
{ "target_url": "https://example.com" }Returns full info about a shortened URL including click count.
Deactivates a shortened URL. The key remains reserved — it cannot be reused.
- Soft deletes — URLs are deactivated (
is_active = False), never removed from the database. This means a deleted custom key cannot be re-registered. - Graceful forward — uses an HTTP
HEADrequest to check target reachability with minimal bandwidth before redirecting. - Secret key — formatted as
{key}_{8-char-random}, returned only at creation time. Store it if you want to manage your link later.
FastAPI's auto-generated docs are available at:
- Swagger UI:
http://localhost:8000/docs - ReDoc:
http://localhost:8000/redoc