Skip to content

tanishqmudaliar/PythonAnywhere-Auto-Renew

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

24 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

PythonAnywhere Auto-Renewal Bot

Automatically renew your PythonAnywhere free web app every 15 days using GitHub Actionsβ€”never let your app expire again!

Python GitHub Actions License Schedule

Main App Demo | Weather Monitoring System


Table of Contents


Overview

PythonAnywhere free tier apps expire after 3 months 1 month of inactivity (updated Jan 2026). This bot automatically renews your web app by logging into PythonAnywhere and clicking the "Extend" button every 15 days via GitHub Actions.

Combined with the Weather-Monitoring-System auto-deployment webhook, this creates a completely hands-off hosting solution that stays alive indefinitely on the free tier.

The Problem

Day 1:   Deploy app βœ…
Day 30:  App expires ❌
Day 31:  Users see error page 😒
Day 32:  Manual renewal... again 😀

The Solution

Day 1:   Deploy app βœ…
Day 15:  Bot auto-renews βœ…
Day 30:  Bot auto-renews βœ…
...forever! πŸŽ‰

Features

Automation

  • Scheduled renewal on the 1st and 15th of every month (04:00 UTC / 09:30 IST)
  • Manual trigger available from GitHub Actions tab
  • Automatic log commits prevent GitHub from disabling the workflow

Logging & Monitoring

  • Complete audit trail in .github/logs/workflow_runs.log
  • Clear SUCCESS βœ… or FAILED ❌ status indicators
  • Timestamps, run IDs, and trigger source for debugging

Security

  • Credentials stored as encrypted GitHub Secrets
  • Never exposed in logs or code
  • HTTPS for all PythonAnywhere connections

Tech Stack

Component Technologies
Language Python 3.9+
Libraries requests, beautifulsoup4, python-dotenv
CI/CD GitHub Actions
Target PythonAnywhere Free Tier

Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                    FULLY AUTOMATED PYTHONANYWHERE HOSTING                   β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                             β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚  β”‚                              GITHUB                                  β”‚   β”‚
β”‚  β”‚                                                                      β”‚   β”‚
β”‚  β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚   β”‚
β”‚  β”‚   β”‚  Weather-Monitoring-System  β”‚  β”‚  PythonAnywhere-Auto-Renew  β”‚   β”‚   β”‚
β”‚  β”‚   β”‚                             β”‚  β”‚                             β”‚   β”‚   β”‚
β”‚  β”‚   β”‚  β€’ Main application code    β”‚  β”‚  β€’ Renewal bot (this repo)  β”‚   β”‚   β”‚
β”‚  β”‚   β”‚  β€’ Deployment endpoint      β”‚  β”‚  β€’ Runs 1st & 15th monthly  β”‚   β”‚   β”‚
β”‚  β”‚   β”‚  β€’ Auto-deploys on push     β”‚  β”‚  β€’ Keeps app alive forever  β”‚   β”‚   β”‚
β”‚  β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚   β”‚
β”‚  β”‚                  β”‚ POST request                   β”‚ GitHub           β”‚   β”‚
β”‚  β”‚                  β”‚ (/github-webhook)              β”‚ Actions          β”‚   β”‚
β”‚  β”‚                  β–Ό                                β–Ό                  β”‚   β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚                     β”‚                                β”‚                      β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚  β”‚                            PYTHONANYWHERE                            β”‚   β”‚
β”‚  β”‚                                                                      β”‚   β”‚
β”‚  β”‚      β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”      β”‚   β”‚
β”‚  β”‚      β”‚   Deployment Endpoint   β”‚    β”‚     Auto-Renewal        β”‚      β”‚   β”‚
β”‚  β”‚      β”‚  β€’ git pull             β”‚    β”‚  β€’ Extends app expiry   β”‚      β”‚   β”‚
β”‚  β”‚      β”‚  β€’ pip install          β”‚    β”‚  β€’ Prevents shutdown    β”‚      β”‚   β”‚
β”‚  β”‚      β”‚  β€’ Reload webapp        β”‚    β”‚  β€’ Zero maintenance     β”‚      β”‚   β”‚
β”‚  β”‚      β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜      β”‚   β”‚
β”‚  β”‚                                                                      β”‚   β”‚
β”‚  β”‚              https://tanishqmudaliar.pythonanywhere.com              β”‚   β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚                                                                             β”‚
β”‚               Push code β†’ Instantly live β†’ Stays alive forever              β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

How It Works

  1. GitHub Actions runs the workflow on the 1st and 15th of each month
  2. Python script logs into PythonAnywhere using your credentials
  3. Script navigates to the web apps dashboard
  4. If an "Extend" button is found, it clicks to renew
  5. Result (success/failure) is logged and committed
  6. Regular commits keep the workflow from being auto-disabled

Getting Started

Prerequisites

  • PythonAnywhere free account with a web app
  • GitHub account
  • 5 minutes of setup time

Quick Setup

Step 1: Fork or Clone

git clone https://github.com/tanishqmudaliar/PythonAnywhere-Auto-Renew.git
cd PythonAnywhere-Auto-Renew

Or click "Use this template" on GitHub.

Step 2: Add GitHub Secrets

  1. Go to your repository β†’ Settings β†’ Secrets and variables β†’ Actions
  2. Click New repository secret and add:
Secret Name Value
PA_USERNAME Your PythonAnywhere username
PA_PASSWORD Your PythonAnywhere password

Step 3: Enable Workflow Permissions

  1. Go to Settings β†’ Actions β†’ General
  2. Under Workflow permissions, select "Read and write permissions"
  3. Check "Allow GitHub Actions to create and approve pull requests"
  4. Click Save

Step 4: Test the Workflow

  1. Go to the Actions tab
  2. Click Auto-Renew PythonAnywhere
  3. Click Run workflow β†’ Run workflow
  4. Verify logs show "βœ… Login successful"

Local Testing

  1. Install dependencies

    pip install -r requirements.txt
  2. Create .env file

    PA_USERNAME=your_username
    PA_PASSWORD=your_password
  3. Run the script

    python renew_python_anywhere.py

Expected output:

πŸ” Logging in as your_username...
βœ… Login successful
πŸ“Š Checking dashboard...
ℹ️  No extend button found.
   This usually means your app doesn't need renewal yet.

Project Structure

PythonAnywhere-Auto-Renew/
β”œβ”€β”€ .github/
β”‚   β”œβ”€β”€ workflows/
β”‚   β”‚   └── renew.yml              # GitHub Actions workflow
β”‚   └── logs/
β”‚       └── workflow_runs.log      # Auto-generated run history
β”œβ”€β”€ renew_python_anywhere.py       # Main renewal script
β”œβ”€β”€ requirements.txt               # Python dependencies
β”œβ”€β”€ .env                           # Local credentials (not in git)
β”œβ”€β”€ .gitignore                     # Git ignore rules
β”œβ”€β”€ LICENSE                        # MIT License
└── README.md                      # Project documentation

Configuration

Environment Variables

Variable Description Required
PA_USERNAME PythonAnywhere username Yes
PA_PASSWORD PythonAnywhere password Yes

Schedule Customization

Edit .github/workflows/renew.yml to change the cron schedule:

# Current: 1st and 15th at 04:00 UTC
- cron: '0 4 1,15 * *'

# Alternative: Every Monday at noon UTC
- cron: '0 12 * * 1'

# Alternative: Every 10 days
- cron: '0 4 1,11,21 * *'

Workflow Logs

Every run is logged to .github/logs/workflow_runs.log:

Success Entry

========================================
Workflow Run: 2026-01-15 04:00:00 UTC
Status: SUCCESS βœ…
Trigger: schedule
Repository: username/PythonAnywhere-Auto-Renew
Branch: main
Run ID: 123456789
Run Number: 5
========================================

Failure Entry

========================================
Workflow Run: 2026-01-15 04:00:00 UTC
Status: FAILED ❌
Trigger: schedule
Repository: username/PythonAnywhere-Auto-Renew
Branch: main
Run ID: 123456790
Run Number: 6
Note: Check GitHub Actions logs for error details
========================================

Related Repositories

Repository Purpose
Weather-Monitoring-System Main weather app with auto-deployment webhook
PythonAnywhere-Auto-Renew Keeps the app alive on free tier (this repo)

Together, these repositories provide:

  • Instant automated deployment on every push
  • 24/7 uptime without manual intervention
  • Zero-maintenance free-tier hosting

Troubleshooting

"Login failed"

  • Verify PA_USERNAME and PA_PASSWORD secrets are correct
  • Try logging in manually to confirm credentials work
  • Check if PythonAnywhere changed their login page

"No extend button found"

  • This is normal, your app doesn't need renewal yet
  • The button only appears when renewal is due
  • Logged as SUCCESS βœ… (not an error)

"Workflow disabled"

  • GitHub disables inactive workflows after 60 days
  • This bot commits logs every 15 days to prevent this
  • Re-enable manually if needed, then run the workflow

Log shows "FAILED ❌"

  • Check the GitHub Actions workflow run for detailed error logs
  • Common causes: wrong credentials, PythonAnywhere site changes
  • Workflow retries automatically on the next scheduled run

Contributing

Contributions are welcome! Please feel free to submit pull requests or open issues.

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/improvement)
  3. Commit your changes (git commit -m 'Add improvement')
  4. Push to the branch (git push origin feature/improvement)
  5. Open a Pull Request

License

This project is open source and available under the MIT License.


Made with ❀️ for PythonAnywhere users

Stop manually clicking that extend button. Automate it! πŸš€

About

A Python automation script that keeps free PythonAnywhere web apps active indefinitely by automatically clicking the renewal button using Selenium and GitHub Actions.

Topics

Resources

License

Stars

Watchers

Forks

Contributors

Languages