
A URL shortener is a web application that transforms lengthy, complex URLs into shorter, easy-to-share links. Platforms like Bitly, TinyURL, and Rebrandly offer this functionality, but building your own URL shortener is an excellent way to learn web development with Python, Flask, and SQLite.
This hands-on guide walks you through creating a fully functional URL shortener from scratch. You’ll gain experience in routing, database operations, templating, and user redirection — all essential concepts for building production-grade web applications.
1. Prerequisites
To follow along, ensure you have the following installed and understood:
- Python 3.7 or later
- pip (Python package manager)
- Basic knowledge of Python programming
- Familiarity with Flask and HTML
- Access to a terminal or command-line interface
2. Project Setup
Step 1: Create a Project Directory
mkdir flask-url-shortener
cd flask-url-shortener
Step 2: Set Up a Virtual Environment
python -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
Step 3: Install Flask
pip install Flask
3. Application Structure
Your project should follow this structure:
flask-url-shortener/
│
├── app.py
├── templates/
│ ├── home.html
│ └── result.html
└── database.db (auto-generated after first run)
4. Creating the Flask Application
app.py
This file contains the application logic including database setup, routing, URL generation, and redirection.
from flask import Flask, render_template, request, redirect
import sqlite3
import string
import random
import os
app = Flask(__name__)
# Database initialization
def init_db():
if not os.path.exists('database.db'):
conn = sqlite3.connect('database.db')
conn.execute('''
CREATE TABLE IF NOT EXISTS urls (
id INTEGER PRIMARY KEY AUTOINCREMENT,
original TEXT NOT NULL,
short TEXT NOT NULL UNIQUE
)
''')
conn.close()
# Generate a random short string
def generate_short_id(num_chars=6):
return ''.join(random.choices(string.ascii_letters + string.digits, k=num_chars))
@app.route('/', methods=['GET', 'POST'])
def home():
if request.method == 'POST':
original_url = request.form['original_url']
# Basic validation
if not original_url.startswith(('http://', 'https://')):
original_url = 'http://' + original_url
short_id = generate_short_id()
conn = sqlite3.connect('database.db')
cursor = conn.cursor()
# Ensure uniqueness
while True:
cursor.execute('SELECT * FROM urls WHERE short = ?', (short_id,))
if not cursor.fetchone():
break
short_id = generate_short_id()
cursor.execute('INSERT INTO urls (original, short) VALUES (?, ?)', (original_url, short_id))
conn.commit()
conn.close()
short_url = request.host_url + short_id
return render_template('result.html', short_url=short_url)
return render_template('home.html')
@app.route('/<short_id>')
def redirect_url(short_id):
conn = sqlite3.connect('database.db')
cursor = conn.cursor()
cursor.execute('SELECT original FROM urls WHERE short = ?', (short_id,))
row = cursor.fetchone()
conn.close()
if row:
return redirect(row[0])
else:
return '<h1>URL not found</h1>', 404
if __name__ == '__main__':
init_db()
app.run(debug=True)
5. HTML Templates
templates/home.html
<!DOCTYPE html>
<html>
<head>
<title>URL Shortener</title>
<meta charset="UTF-8">
</head>
<body>
<h1>Flask URL Shortener</h1>
<form method="POST">
<label for="original_url">Enter a long URL:</label><br>
<input type="url" id="original_url" name="original_url" required placeholder="https://example.com"><br><br>
<button type="submit">Shorten URL</button>
</form>
</body>
</html>
templates/result.html
<!DOCTYPE html>
<html>
<head>
<title>Shortened URL</title>
<meta charset="UTF-8">
</head>
<body>
<h1>Your shortened URL</h1>
<p><a href="{{ short_url }}">{{ short_url }}</a></p>
<a href="/">Shorten another URL</a>
</body>
</html>
6. Running the Application
To run the app locally:
python app.py
Visit http://127.0.0.1:5000
in your browser. You can now enter long URLs and receive shortened versions that redirect accordingly.
7. Optional Enhancements
Here are several ideas to expand and improve the functionality:
a. Custom Aliases
Allow users to specify their own short IDs instead of random strings. Ensure uniqueness before saving.
b. URL Expiration
Add expiration timestamps for temporary URLs and delete them automatically.
c. Click Tracking and Analytics
Store data like access time, IP address, or referrer. Useful for monitoring usage and analytics.
d. User Accounts
Add authentication to manage personal URL dashboards, edit or delete links.
e. RESTful API
Build a public API that supports POST requests for link creation and GET for redirection.
f. Frontend Styling
Use Bootstrap or Tailwind CSS for a better user interface.
g. Persistent Logging
Store logs of errors and user interactions for audit and debugging purposes.
h. URL Validation
Use libraries like validators
or regex to validate URL format before saving.
8. Deployment Suggestions
Once your app is ready, deploy it using:
- Render (easy GitHub integration)
- Heroku (free tier with limited hours)
- Docker + VPS (customizable deployment)
- PythonAnywhere (simple Flask hosting)
- Netlify + API Gateway (for frontend/backend separation)
Use gunicorn or uWSGI for production server handling instead of Flask’s built-in development server.
Final Thoughts
Building your own URL shortener with Flask and SQLite is an excellent project for solidifying foundational web development skills. It covers database design, HTTP routing, form handling, redirection, and dynamic HTML rendering.
Once complete, you will have a fully functional microservice — with plenty of opportunities to extend it into a more advanced web application.

I’m Shreyash Mhashilkar, an IT professional who loves building user-friendly, scalable digital solutions. Outside of coding, I enjoy researching new places, learning about different cultures, and exploring how technology shapes the way we live and travel. I share my experiences and discoveries to help others explore new places, cultures, and ideas with curiosity and enthusiasm.