You've built your Django project locally. It runs fine on localhost:8000.
Now you want the world to see it. PythonAnywhere is the easiest place to host a
Django app for free — no server setup, no Linux knowledge required, just a browser and your code.
What Is PythonAnywhere?
PythonAnywhere is a cloud platform built specifically for Python. Unlike AWS or DigitalOcean, you don't configure servers, install packages globally, or worry about firewalls. They handle the infrastructure. You just upload your code and point a few config files at it.
The free tier gives you one web app at a yourusername.pythonanywhere.com
subdomain, a MySQL database, and a Linux console you can use from the browser. That's enough
to deploy a real Django project.
The Big Picture Before You Start
Here's the full journey from your laptop to a live URL — so nothing surprises you mid-way:
- Create a free PythonAnywhere account
- Open a Bash console and clone your project from GitHub (or upload files manually)
- Create a virtual environment and install your dependencies
- Set up the web app via the PythonAnywhere dashboard
- Configure the WSGI file to point at your Django project
- Set environment variables (SECRET_KEY, DEBUG, DATABASE_URL)
- Run migrations and collect static files
- Reload the app — done
PythonAnywhere runs your Django app through a WSGI server. When someone visits your URL,
their server calls your Django app the same way runserver does locally —
just without the development warnings.
Step 1 — Create Your Account
Go to pythonanywhere.com and
sign up for a free Beginner account. Your username becomes part of your live URL —
yourusername.pythonanywhere.com — so pick something you're comfortable sharing.
After signup you land on the Dashboard. The important tabs are: Consoles, Web, and Files. You'll use all three.
Step 2 — Open a Bash Console
Click Consoles → Bash. This opens a real Linux terminal
in your browser. Your files live at /home/yourusername/.
The fastest way to get your code onto PythonAnywhere is from GitHub. If your project is in a repo, clone it now:
git clone https://github.com/yourusername/yourproject.git
If you don't have a GitHub repo yet, you can upload files manually through the Files tab, or use the console to create files directly. GitHub is strongly recommended — it makes future updates a one-command operation.
Step 3 — Create a Virtual Environment
Always use a virtual environment. It keeps your project's packages isolated from PythonAnywhere's system Python and from other projects on the same account.
# Navigate into your project folder
cd yourproject
# Create a virtualenv — match the Python version you used locally
python3.12 -m venv venv
# Activate it
source venv/bin/activate
# Your prompt now shows (venv) — all pip installs go here
pip install -r requirements.txt
If you don't have a requirements.txt, generate one locally first with
pip freeze > requirements.txt and push it to GitHub.
After installing, verify Django is available:
python -c "import django; print(django.__version__)"
Step 4 — Create the Web App
Go to the Web tab in the PythonAnywhere dashboard and click Add a new web app. Walk through the wizard:
- Domain — on the free plan it's fixed as
yourusername.pythonanywhere.com - Framework — select Manual configuration (not the "Django" option — that creates a new blank project)
- Python version — match what you used locally (3.12 recommended)
After clicking through, PythonAnywhere creates a default WSGI file and shows you the web app configuration page. Keep this page open — you'll edit several fields here.
Step 5 — Configure the WSGI File
The WSGI file is the bridge between PythonAnywhere's server and your Django app.
On the Web tab, click the link next to WSGI configuration file
— it will be something like /var/www/yourusername_pythonanywhere_com_wsgi.py.
Delete everything in that file and replace it with this:
import sys
import os
# Add your project directory to the Python path
path = '/home/yourusername/yourproject'
if path not in sys.path:
sys.path.insert(0, path)
# Tell Django which settings file to use
os.environ['DJANGO_SETTINGS_MODULE'] = 'yourproject.settings'
# Load the Django WSGI application
from django.core.wsgi import get_wsgi_application
application = get_wsgi_application()
Replace yourusername with your actual PythonAnywhere username,
yourproject with your project folder name, and
yourproject.settings with the Python path to your settings module
(the same value you'd use in DJANGO_SETTINGS_MODULE locally).
Step 6 — Set the Virtualenv Path
Back on the Web tab, scroll to the Virtualenv section. Enter the full path to your virtual environment:
/home/yourusername/yourproject/venv
PythonAnywhere will validate the path and show a green checkmark if it finds it. This tells the WSGI server to use your project's packages, not the system ones.
Step 7 — Fix Your settings.py for Production
A settings file that works locally will break in production if you don't update a few values.
Open your settings.py in the PythonAnywhere file editor or via the console:
# settings.py — production changes
# 1. Turn DEBUG off — never run with DEBUG=True in production
DEBUG = False
# 2. Add your PythonAnywhere domain
ALLOWED_HOSTS = ['yourusername.pythonanywhere.com']
# 3. Tell Django where static files are served from
STATIC_URL = '/static/'
STATIC_ROOT = '/home/yourusername/yourproject/staticfiles'
# 4. For media uploads (if you use ImageField / FileField)
MEDIA_URL = '/media/'
MEDIA_ROOT = '/home/yourusername/yourproject/media'
Keep your SECRET_KEY secret. Don't commit it to GitHub.
The safest approach is to read it from an environment variable:
import os
SECRET_KEY = os.environ.get('SECRET_KEY', 'fallback-for-local-dev-only')
You set the actual value in the Environment variables section on the Web tab.
Step 8 — Static Files
Django's runserver serves static files automatically in development.
In production it doesn't — a proper web server does that. You need to collect all
your static files into one folder and tell PythonAnywhere where to serve them from.
In the Bash console (with your virtualenv active):
cd /home/yourusername/yourproject
python manage.py collectstatic
This copies everything from your app's static/ folders into
STATIC_ROOT (/home/yourusername/yourproject/staticfiles).
Now go to the Web tab, scroll to Static files, and add a mapping:
URL: /static/
Directory: /home/yourusername/yourproject/staticfiles
If you use media uploads, add a second mapping:
URL: /media/
Directory: /home/yourusername/yourproject/media
Step 9 — Database Setup
If you're using SQLite (the default for new Django projects), it works on PythonAnywhere
with no extra configuration — the .sqlite3 file just lives in your project folder.
Run your migrations:
python manage.py migrate
If you want a more robust setup, PythonAnywhere's free tier includes a MySQL database.
Go to the Databases tab, create one, and update your
settings.py DATABASES block to use it.
After migrating, create a superuser so you can access the admin panel:
python manage.py createsuperuser
Step 10 — Reload and Visit Your Site
Go back to the Web tab and click the big green Reload button. PythonAnywhere restarts your app with all the new configuration.
Open a new browser tab and go to:
https://yourusername.pythonanywhere.com
If you see your Django homepage — you're live. If you see an error, the next section explains exactly where to look.
Debugging Common Errors
When something goes wrong, the error log tells you exactly what. On the Web tab, click Error log — it's a live log of every exception Django has thrown. Read the last few lines first.
| Error | Most likely cause | Fix |
|---|---|---|
ModuleNotFoundError |
Package not installed in virtualenv, or wrong virtualenv path | Check virtualenv path on Web tab; run pip install again |
DisallowedHost |
Your domain isn't in ALLOWED_HOSTS |
Add yourusername.pythonanywhere.com to ALLOWED_HOSTS |
| Static files returning 404 | Static file URL/directory mapping missing or wrong path | Re-run collectstatic; check the mapping on the Web tab |
OperationalError: no such table |
Migrations haven't been run | Run python manage.py migrate in the console |
| 500 error with blank page | DEBUG = False hides the error details |
Check the error log — the traceback is always there even with DEBUG off |
| Old code still showing | App not reloaded after code change | Click Reload on the Web tab every time you change Python files |
Updating Your Site After Changes
Every time you push new code to GitHub and want it live, the workflow is:
# In PythonAnywhere Bash console
cd /home/yourusername/yourproject
# Pull the latest code
git pull origin main
# If you added new packages
source venv/bin/activate
pip install -r requirements.txt
# If you changed models
python manage.py migrate
# If you changed static files
python manage.py collectstatic --noinput
Then go to the Web tab and hit Reload. That's the entire deployment process for every future update.
Pre-Launch Checklist
DEBUG = Falsein settings- Your domain in
ALLOWED_HOSTS SECRET_KEYnot committed to GitHub — loaded from environment- Virtualenv path set correctly on Web tab
- WSGI file updated with correct project path and settings module
- Static files URL/directory mapping added on Web tab
collectstatichas been runmigratehas been run- Superuser created — admin panel accessible at
/admin/ - Reload clicked after all changes
PythonAnywhere's free tier has one limitation worth knowing: your app goes to sleep after 3 months of inactivity unless you log in and click a "keep alive" button on the Web tab. Set a monthly reminder and you'll never lose your deployment.
Next in the series: connecting a custom domain to PythonAnywhere and switching from SQLite to a production MySQL database.