Building a URL Shortener Service in Python Flask

Building a URL Shortener Service in Python Flask

Building a URL Shortener Service in Python Flask

 

Introduction

We’ve all used URL shorteners like Bitly or TinyURL — they take a long, messy URL and turn it into something concise and shareable. In this tutorial, you’ll learn how to build your own mini URL shortener using Python Flask. The best part? You can do it all in under 50 lines of code. Along the way, we’ll walk through route setup, database storage, and redirect logic, while keeping the app clean and functional.

1. Setting Up the Project

First, let’s create a new directory for our Flask app and install the dependencies:

mkdir flask_url_shortener
cd flask_url_shortener
pip install flask sqlite3

Then, create a file called app.py. Import the required modules and initialize the app:

from flask import Flask, request, redirect, render_template_string
import sqlite3, string, random

app = Flask(__name__)

This sets up the basic structure of our Flask application. We’ll be using SQLite for simplicity—it’s lightweight, file-based, and perfect for a small project like this.

2. Database Setup and URL Storage

Next, we need a place to store the long URLs and their corresponding short codes. Let’s create a small helper function to manage database connections and initialize a table:

def get_db():
    conn = sqlite3.connect('data.db')
    conn.execute('CREATE TABLE IF NOT EXISTS urls (code TEXT, url TEXT)')
    return conn

This ensures that every time the app runs, a database file called data.db exists and has a table to hold URL data. Using SQLite also keeps our project self-contained with no need for additional servers.

3. Generating Unique Short Codes

Each long URL needs a randomly generated short code. We can use letters and digits for this:

def generate_code(length=6):
    chars = string.ascii_letters + string.digits
    return ''.join(random.choice(chars) for _ in range(length))

The generate_code() function ensures uniqueness by producing different combinations each time. For production, you’d want to include an existence check and maybe hash the original URL to avoid duplicates, but for our lightweight version, this is fine.

4. Flask Routes: Shortening and Redirecting

Now we’ll define the main two routes: one for shortening a URL and one for handling redirects.

a. Home route to shorten URLs:

@app.route('/', methods=['GET', 'POST'])
def home():
    if request.method == 'POST':
        url = request.form['url']
        code = generate_code()
        conn = get_db()
        conn.execute('INSERT INTO urls VALUES (?, ?)', (code, url))
        conn.commit()
        conn.close()
        return f'Shortened URL: <a href=\"/{code}\">localhost:5000/{code}</a>'
    return render_template_string('<form method=\"post\"><input name=\"url\"/><input type=\"submit\"/></form>')

When a user submits a URL, it’s saved in the database with its short code. The page then displays the shortened link, ready for sharing.

b. Redirect route:

@app.route('/')
def redirect_to_url(code):
    conn = get_db()
    cursor = conn.execute('SELECT url FROM urls WHERE code = ?', (code,))
    row = cursor.fetchone()
    conn.close()
    if row:
        return redirect(row[0])
    return 'URL not found', 404

This route captures the short code from the path and looks it up in the database. If found, Flask’s redirect() function sends users to the original long URL. If not found, it returns a 404 error.

5. Running and Testing the App

Now we can start our app:

if __name__ == '__main__':
    app.run(debug=True)

Run the program using python app.py and visit http://localhost:5000. Paste a long URL into the form, click submit, and you’ll get a shortened link. Open it in your browser, and—voilà—it redirects correctly.

6. Tips and Optimizations

Though this app is intentionally minimal, you can enhance it further:

  • Use hashed short codes for consistency.
  • Implement expiration or click tracking features.
  • Add input validation and error handling.
  • Use SQLAlchemy or an ORM for maintainability.
  • Host it on platforms like Render or Railway for quick deployment.

Even in under 50 lines, you can build something surprisingly functional. This small project demonstrates how Flask and SQLite can work together to power a real-world microservice. It’s an excellent starting point for learning about RESTful design, route handling, and lightweight persistence in Python.

 

Useful links: