Get Rewarded! We will reward you with up to €50 credit on your account for every tutorial that you write and we publish!

Auto-Shutdown Hetzner VPS at the Bandwidth Limit to Avoid Overcharges

profile picture
Author
Robin Roy
Published
2025-07-28
Time to read
5 minutes reading time

About the author- Building things that make the world a better place.

Introduction

This tutorial walks you through automatically shutting down your Hetzner VPS once its monthly bandwidth crosses a specified limit (e.g., 19 TB). This is useful to avoid overage charges and maintain control over your server usage.

By following this guide, you'll install a Python-based monitoring script, configure your Hetzner Cloud API, and set up a cron job that runs every 30 minutes to check and shut down your VPS when needed.

Prerequisites

Step 1 - Get Your Hetzner API Key and Server ID

  1. Go to the Hetzner Console.
  2. Create an API token from the project settings.
  3. Your HETZNER_SERVER_ID is the last part of the URL when you visit your server:
    https://console.hetzner.com/projects/<PROJECT_ID>/servers/<SERVER_ID>/overview
    Save both values securely, you will need them in the script.

Step 2 - Install the script on the VPS

  1. SSH into your Hetzner VPS:

    ssh root@<your_host>
  2. Create a bandwidth_monitor.py file in your machine with the following content. Replace the <YOUR_API_TOKEN_HERE> and <YOUR_HETZNER_SERVER_ID_HERE> with the values you saved in step 1:

    import os
    import urllib.request
    import urllib.error
    import json
    import sys
    from datetime import datetime
    
    API_TOKEN = "<YOUR_API_TOKEN_HERE>"
    SERVER_ID = "<YOUR_HETZNER_SERVER_ID_HERE>"
    
    print(f"[{datetime.now()}] Script ran")
    if not API_TOKEN or not SERVER_ID:
        print("Error: HETZNER_API_TOKEN and HETZNER_SERVER_ID must be set.")
        sys.exit(1)
    
    TB = 1024**4
    GB = 1024**3
    SHUTDOWN_THRESHOLD_BYTES = 19 * TB
    
    
    url = f"https://api.hetzner.cloud/v1/servers/{SERVER_ID}"
    headers = {"Authorization": f"Bearer {API_TOKEN}"}
    
    try:
        req = urllib.request.Request(url, headers=headers)
        with urllib.request.urlopen(req) as response:
            data = json.loads(response.read().decode('utf-8'))
    except urllib.error.HTTPError as e:
        print(f"HTTP Error fetching server data: {e.code} {e.reason}")
        sys.exit(1)
    except Exception as e:
        print(f"Error fetching server data: {e}")
        sys.exit(1)
    
    server = data.get("server", {})
    status = server.get("status", "unknown")
    outgoing_traffic = server.get("outgoing_traffic") or 0
    
    print(f"Current outgoing traffic: {outgoing_traffic / GB:.2f} GB")
    
    if status == "running":
        if outgoing_traffic >= SHUTDOWN_THRESHOLD_BYTES:
            print("19 TB limit reached. Sending shutdown request...")
            try:
                shutdown_req = urllib.request.Request(f"{url}/actions/shutdown", method='POST', headers=headers)
                with urllib.request.urlopen(shutdown_req) as response:
                    print("Shutdown request sent successfully.")
            except urllib.error.HTTPError as e:
                print(f"HTTP Error during shutdown: {e.code} {e.reason}")
            except Exception as e:
                print(f"Error during shutdown: {e}")
        else:
            print("Server running, but under 19 TB. No action taken.")
    else:
        print(f"Server is not running (status: {status})")

Step 3 - Set up a cron job to run the script every 30 minutes

Use the crontab -e command in the terminal to open the crontab editor and add the following line to run the script every 30 minutes:

*/30 * * * * cd /path/to/hetzner-bandwidth-script && /usr/bin/python3 bandwidth_monitor.py >> cron.log 2>&1

The path to the script depends on where you saved it. Use pwd command to check the current directory. Always use the full path to the script. cron.log will log all output from the script. You can view the logs by running cat cron.log in the same directory.

Step 4 - Adjust the Bandwidth Threshold (Optional)

In your Python script (bandwidth_monitor.py), the bandwidth threshold is set to 19 TB by default. You can change this value if you want to trigger the shutdown at a different usage level.

SHUTDOWN_THRESHOLD_BYTES = 19 * TB      # modify this value to your desired threshold

Step 5 - Test the script

Run the script manually to test it:

python3 bandwidth_monitor.py

You should see the output in the terminal. If the script detects that the bandwidth has crossed the threshold, it will send a shutdown request to the Hetzner API. Also, check your cron.log file to verify that the script ran successfully every 30 minutes.

Conclusion

You've successfully automated your Hetzner VPS to shut down when the bandwidth threshold is reached. This setup helps prevent unexpected overcharges and allows for better resource management.

License: MIT
Want to contribute?

Get Rewarded: Get up to €50 in credit! Be a part of the community and contribute. Do it for the money. Do it for the bragging rights. And do it to teach others!

Report Issue
Try Hetzner Cloud

Get €20/$20 free credit!

Valid until: 31 December 2025 Valid for: 3 months and only for new customers
Get started
Want to contribute?

Get Rewarded: Get up to €50 credit on your account for every tutorial you write and we publish!

Find out more