How to schedule a Python script on cPanel shared hosting

Table of Contents

If you have ever tried to schedule a Python script on shared hosting, you have probably landed on this page after a few hours of clicking through outdated tutorials. The script does not run. No error email arrives. The cron entry looks correct. This guide is the version I wish I had read on day one: a clean walk-through of the only three pieces you actually need, plus the four pitfalls that explain 90% of the silent failures.

You don’t need root access, Docker, or a VPS for daily Python jobs. A standard cPanel account with cron jobs and the Python App selector is enough for the vast majority of automation tasks: sending scheduled emails, refreshing reports, syncing data, running lightweight webhooks, processing queued items.

What you need before you start

  • A cPanel account with access to Advanced → Cron Jobs and Software → Setup Python App.
  • An FTP/SFTP client or the cPanel File Manager to upload your script.
  • A script that already runs correctly when you call it from the command line.

All shared hosting plans at Liberty Dreams include cPanel with cron jobs and Python App selectors as standard. If your current host doesn’t, that is the first thing to check before debugging anything else.

Step 1: Pick the right Python interpreter

On shared hosting you generally have two sane options:

  • Setup Python App (recommended): the cPanel module that creates a virtual environment and an entry point. It writes the exact source .../activate line you must call from cron, so there is no guesswork about the Python path.
  • System Python (fallback): if your host doesn’t offer Setup Python App, you can still use the system’s python3. The catch is that python3 may not be in the cron PATH, and the available version may not match what you developed against.

Avoid cgi-bin/python3 for scheduled work. It is the legacy route, poorly documented, and a frequent source of subtle permission errors.

Step 2: Write a small wrapper script

The wrapper is what the cron job will actually call. It exists for three reasons: to load the correct Python environment, to set a known working directory, and to capture logs so you can see what failed.

A minimal, reliable wrapper looks like this:

#!/bin/bash
set -euo pipefail

# 1. Go to the script directory (cron runs from $HOME otherwise)
cd "$HOME/scripts/myapp" || exit 1

# 2. Activate the virtualenv created by Setup Python App
#    (copy the exact path from cPanel → Setup Python App → "Enter to the virtual environment")
source "$HOME/virtualenvs/myapp/bin/activate"

# 3. Load environment variables if your script needs them
set -a
source .env
set +a

# 4. Run the script and capture all output
mkdir -p "$HOME/logs"
python main.py >> "$HOME/logs/myapp.log" 2>&1

Two details that matter more than they look:

  • cd "$HOME/scripts/myapp" — cron runs every command with the working directory set to your account home, not the script directory. Anything that opens a file with a relative path will silently fail without this.
  • >> "$HOME/logs/myapp.log" 2>&1 — without redirection, output goes nowhere and you cannot tell whether the job ran or not.

Save the file as run.sh, upload it, and make it executable from the File Manager (right-click → Permissions → 0755) or via FTP.

Step 3: Add the cron entry in cPanel

  • Log in to cPanel (typically https://yourdomain:2083 or https://cpanel.yourdomain:2083 or https://yourdomain.com/cpanel).
  • Open Cron Jobs.
  • Set a notification email or, if you would rather not be emailed on every error, leave it blank and rely on the log file.
  • Under Common Settings, pick the schedule you want. For most daily automations, Once per day at a quiet hour is the right starting point.
  • In the Command field, paste the full absolute path to the wrapper:
    /home/youraccount/scripts/myapp/run.sh
  • Click Add New Cron Job.

That is the entire setup. If the wrapper and paths are correct, the job will run on schedule.

The four silent failures (and how to spot each)

These four account for the overwhelming majority of “my cron does not work” tickets on shared hosting:

1. command not found in the log

Cause: cron has a stripped-down PATH that does not include python3. Fix: always call the Python binary by its absolute path, or activate the virtualenv in the wrapper as shown above.

2. The job runs but the output is empty

Cause: relative paths in your script. The wrapper fixes this for the script itself, but if your script opens other files by relative path, it is reading from $HOME, not the script directory. Fix: either use absolute paths in the script or cd inside the script as well.

3. ModuleNotFoundError even though pip install worked

Cause: the cron environment is not using your virtualenv. The wrapper must source the activate script before running Python, and you must have installed the dependencies into that same virtualenv.

4. Database connection error with no helpful message

Cause: environment variables (database URL, API keys, secrets) are not loaded. Cron does not inherit shell .bashrc or .profile. Fix: load them explicitly in the wrapper using set -a; source .env; set +a or pass them inline in the cron command.

Frequently asked questions

What if my hosting does not have Setup Python App?

Use the system python3 binary directly and call it with the explicit version that ships on the server (for example python3.11). If your host offers neither a Python App selector nor a usable system Python, it is not a viable environment for scheduled Python work, and switching providers or develop your code in php is the pragmatic answer.

Can I run Flask or FastAPI this way?

You can run them as scripts (a CLI entry point, a one-shot request, a queue worker). You can’t expose them as long-running web servers from cron, for that you would need a process manager or a VPS. If your use case is “hit an internal endpoint every hour”, that is a perfect fit for cron.

How do I test before scheduling?

Run the wrapper from SSH with the same user the job will run as. If it works there and fails under cron, the difference is almost always the working directory, the PATH, or the environment variables. The wrapper’s cd and source lines remove two of those three.

Summary

Scheduling Python on cPanel comes down to three things done correctly: pick the right Python interpreter (Setup Python App whenever possible), write a wrapper that fixes the working directory, the environment, and the logging, and call that wrapper by absolute path from the cron entry. Once those are in place, the rest of the troubleshooting is normal Python debugging.

If you are evaluating a host specifically for scheduled Python work, the three things worth checking before signing up are: that cPanel’s Setup Python App is available, that cron jobs can run with a five-minute or finer resolution, and that the documentation lists the supported Python versions clearly. The Liberty Dreams shared hosting range includes all three on every tier, plus JetBackup for restoring a broken environment in minutes.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may also be interested in...