Fortnite goes down for scheduled maintenance roughly every two weeks, and when it does, millions of players hit refresh on the same three questions: is it down for everyone, how long will it take, and how do I find out the second it’s back. Epic Games posts a status page, but it doesn’t text you. Third-party outage trackers lag by minutes. If you want to know the instant Chapter 7 Season 4 servers come back online in your own time zone, you have to build that yourself.
This tutorial walks through building a small, self-hosted Python tool that polls Epic’s official status API, converts the maintenance window into your local time, and fires a free push notification the moment matchmaking is re-enabled. It’s a weekend project, not a product. By the end you’ll have a script you can leave running on a Raspberry Pi, a home server, or a free-tier cloud box, and it’ll outlast whatever today’s patch number happens to be.
Why build your own Fortnite downtime alert instead of just checking a website
Checking status.epicgames.com manually works fine if you’re sitting at your desk. It stops working the moment you’re asleep, at work, or just tired of alt-tabbing every ten minutes during a Fortnitemares launch. On October 1, 2026, Epic took Fortnite down at 4:00 a.m. ET (8:00 a.m. UTC) to ship update v42.30 and the Fortnitemares 2026 event, and maintenance windows that week ran in the 2.5 to 3 hour range according to uptime trackers like StatusGator. That’s a long stretch to babysit a browser tab.
A script fixes the babysitting problem. Instead of you polling a page, the page polls itself through an API, and it only bothers you once, when the state actually flips from “down” to “up.” The other reason to do this yourself: official downtime windows are always posted in UTC or Eastern Time, and doing that math in your head at 4 a.m. local time is exactly the kind of thing a computer should handle instead of a half-awake brain. If you’re in Manila, Berlin, or São Paulo, “4 AM ET” means something different every single patch, and daylight saving shifts make it worse twice a year.
There’s a second practical reason. Epic’s status page groups several components together (login, matchmaking, game services, cloud saves, the item shop). A script lets you decide which specific component you actually care about and ignore noise from unrelated services. If you only play Battle Royale, you don’t need an alert because cloud save sync hiccuped for 90 seconds.
What you’ll build: the project at a glance
The finished tool is a single Python script plus a small config file. It does four things on a loop: fetch the Epic status JSON, parse out the Fortnite-relevant components, compare the current state against the last known state, and send a push notification through ntfy.sh (a free, open-source notification service with no account required) whenever the state changes. You’ll run it under cron or systemd so it survives reboots.
No Discord bot, no database, no web dashboard. Just a notifier that sits quietly until something changes and then buzzes your phone. That’s a deliberately smaller scope than a full tracker or historical archive, and it’s the part most players actually want: a heads-up the moment the servers are back.
Prerequisites and versions
Here’s exactly what you need before starting. Versions matter less than usual here since the script leans on the standard library, but these are what was used and tested while writing this guide.
| Requirement | Version / Detail |
| Python | 3.11 or newer (for the built-in zoneinfo module) |
| requests library | latest version via pip |
| Operating system | Linux, macOS, or Windows with WSL |
| ntfy.sh account | none needed — topic-based, anonymous by default |
| Scheduler | cron (Linux/macOS) or systemd timer (Linux) or Task Scheduler (Windows) |
| Disk space | under 5 MB for script, config, and logs |
| Network access | outbound HTTPS to status.epicgames.com and ntfy.sh |
You do not need a Fortnite account, an Epic developer key, or any paid API tier. The status endpoint used here is public and unauthenticated, which is also why you should treat it politely (the polling interval in this guide is set to five minutes, not five seconds).
Step 1: Inspect Epic’s status API before writing any code
Before building anything, look at the raw data you’re working with. Epic exposes a status feed at status.epicgames.com/api. Run a quick request from your terminal:
curl -s https://status.epicgames.com/api | python3 -m json.tool | head -40
You’ll get back a JSON document with a top-level status indicator (one of none, minor, major, or critical), a human-readable description, and a list of components with their own individual statuses. Fortnite-specific entries typically include labels like “Fortnite,” “Matchmaking,” and “Game Services.” Note the exact component name you care about, because you’ll filter on it by string match in step 4.
This inspection step matters more than it looks. Status APIs change their JSON shape without warning, and if you skip straight to writing a parser based on a blog post’s example, you’ll build against a schema that might already be stale. Always pull the live response yourself first.
Step 2: Set up the Python project and virtual environment
Keep this isolated from your system Python so a dependency bump somewhere else on your machine can’t break it. Create a project folder and a virtual environment:
mkdir fortnite-downtime-alert
cd fortnite-downtime-alert
python3 -m venv venv
source venv/bin/activate
pip install requests
On Windows, the activation command is venv\Scripts\activate instead of the source line above. Confirm the install worked with pip show requests, which should print a version number and install path. That’s the only third-party dependency this whole project needs.
Step 3: Pick your local time zone and notification channel
Two decisions before writing code. First, your IANA time zone string (for example America/New_York, Europe/Berlin, Asia/Manila) — this is what Python’s zoneinfo module uses to convert Epic’s UTC timestamps into something you’d actually read on a clock. Second, your notification channel. ntfy.sh works by topic name: you pick an unguessable topic string, subscribe to it on your phone with the free ntfy app, and anything posted to that topic over HTTP shows up as a push notification seconds later.
Pick a topic name that’s hard to guess, since ntfy topics are public by default unless you self-host or use their paid tier. Something like fortnite-dt-7x29qz is fine. Avoid anything that includes your real name or anything sensitive, since anyone who knows the exact topic string can subscribe to it too.
Step 4: Write the config file
Separate configuration from logic so you’re not editing Python every time you want to change your time zone or polling interval. Create config.py:
# config.py
STATUS_URL = "https://status.epicgames.com/api"
COMPONENT_MATCH = "Fortnite" # substring to match in component names
LOCAL_TZ = "America/New_York" # swap for your IANA timezone
POLL_SECONDS = 300 # 5 minutes between checks
NTFY_TOPIC = "fortnite-dt-7x29qz" # pick your own, keep it unguessable
STATE_FILE = "last_state.json"
LOG_FILE = "downtime_alert.log"
The POLL_SECONDS value of 300 is deliberate. Epic’s status page updates aren’t real-time to the second, and hammering a free public endpoint every few seconds is bad etiquette for an unauthenticated API with no published rate limit. Five minutes is frequent enough to catch a downtime-to-online transition within a reasonable window without being rude to Epic’s infrastructure.
Step 5: Write the status-fetching function
Now the core logic. Create main.py and start with the function that pulls and parses the status feed:
import json
import time
import logging
from datetime import datetime
from zoneinfo import ZoneInfo
import requests
import config
logging.basicConfig(
filename=config.LOG_FILE,
level=logging.INFO,
format="%(asctime)s %(levelname)s %(message)s",
)
def fetch_status():
response = requests.get(config.STATUS_URL, timeout=10)
response.raise_for_status()
data = response.json()
overall = data.get("status", {}).get("indicator", "unknown")
components = data.get("components", [])
fortnite_components = [
c for c in components
if config.COMPONENT_MATCH.lower() in c.get("name", "").lower()
]
return overall, fortnite_components
This isolates the two things you actually care about: the site-wide indicator and the subset of components that mention “Fortnite” by name. The actual field names can shift slightly between status page providers, so if your curl inspection in step 1 showed a different nesting, adjust the dictionary keys here to match what you saw.
Step 6: Convert the downtime window to your local time
This is the part a plain status-page bookmark can’t do for you. Add a helper that takes a UTC timestamp string and renders it in your configured local time zone:
def to_local_time(utc_iso_string):
utc_dt = datetime.fromisoformat(utc_iso_string.replace("Z", "+00:00"))
local_dt = utc_dt.astimezone(ZoneInfo(config.LOCAL_TZ))
return local_dt.strftime("%Y-%m-%d %I:%M %p %Z")
def describe_window(start_utc, end_utc=None):
start_local = to_local_time(start_utc)
if end_utc:
end_local = to_local_time(end_utc)
return f"Downtime: {start_local} through {end_local}"
return f"Downtime started: {start_local} (no end time posted yet)"
Epic’s incident entries usually include a scheduled start time and, once maintenance wraps up, a completion timestamp. Not every incident object will have both fields populated at every moment, which is why describe_window handles the “still in progress, no end time yet” case separately instead of crashing on a missing key.
Step 7: Track state so you only get notified once per change
Without state tracking, your script would ping you every five minutes for the entire three-hour maintenance window, which defeats the point. Persist the last known status to a small JSON file:
import os
def load_last_state():
if os.path.exists(config.STATE_FILE):
with open(config.STATE_FILE) as f:
return json.load(f)
return {"indicator": "none"}
def save_state(indicator):
with open(config.STATE_FILE, "w") as f:
json.dump({"indicator": indicator}, f)
The pattern is simple: read what the state was last time, compare it to what it is now, and only act when the two differ. This same pattern is the backbone of basically every uptime monitor and alerting tool, from enterprise-grade observability stacks down to a 40-line hobby script like this one.
Step 8: Send the push notification through ntfy
With state tracking in place, wire up the actual alert. ntfy accepts a plain HTTP POST to a topic URL, no API key required for the free public service:
def send_notification(title, message, priority="default"):
url = f"https://ntfy.sh/{config.NTFY_TOPIC}"
headers = {
"Title": title,
"Priority": priority,
}
try:
requests.post(url, data=message.encode("utf-8"), headers=headers, timeout=10)
logging.info("Notification sent: %s", title)
except requests.RequestException as exc:
logging.error("Failed to send notification: %s", exc)
Install the ntfy app (iOS, Android, or a desktop client) and subscribe to the same topic string you put in config.py. Anything posted to that topic from your script now shows up as a push notification within a few seconds, with no account creation and no cost.
Step 9: Write the main polling loop
Now tie everything together into the loop that actually runs continuously:
def run():
last_state = load_last_state()
while True:
try:
overall, fortnite_components = fetch_status()
if overall != last_state.get("indicator"):
if overall == "none":
send_notification(
"Fortnite is back online",
"Epic's status feed shows all systems operational again.",
priority="high",
)
else:
detail = ", ".join(
c.get("status", "unknown") for c in fortnite_components
) or "status changed"
send_notification(
"Fortnite status changed",
f"Overall indicator: {overall}. Components: {detail}",
priority="default",
)
save_state(overall)
last_state["indicator"] = overall
logging.info("Checked status: %s", overall)
except requests.RequestException as exc:
logging.error("Status check failed: %s", exc)
time.sleep(config.POLL_SECONDS)
if __name__ == "__main__":
run()
Run it with python main.py and leave the terminal open to confirm it works before moving it to a scheduler. You should see log lines appending to downtime_alert.log every five minutes, and a notification should land on your phone the next time Fortnite’s status flips.
Step 10: Test it against a known-down state
Don’t wait for the next real outage to find out if your script works. Temporarily hardcode a fake status in fetch_status() to force both branches of the notification logic to fire once each:
# Temporary test override — remove before deploying
def fetch_status():
return "major", [{"name": "Fortnite", "status": "major_outage"}]
Run the script, confirm you get the “status changed” push, stop it, revert the hardcoded return, change the fake value to "none", and run it again to confirm the “back online” push also fires. Delete last_state.json between each test run so the state comparison doesn’t skip the alert because it thinks nothing changed. Only after both notifications land correctly should you point the function back at the real API and consider the core logic done.
Step 11: Run it continuously with systemd or cron
A script that only runs while your laptop lid is open isn’t much of an alert system. On Linux, a systemd service keeps it running and restarts it automatically if it crashes. Create /etc/systemd/system/fortnite-alert.service:
[Unit]
Description=Fortnite downtime alert
After=network-online.target
[Service]
WorkingDirectory=/home/youruser/fortnite-downtime-alert
ExecStart=/home/youruser/fortnite-downtime-alert/venv/bin/python main.py
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
Enable and start it:
sudo systemctl daemon-reload
sudo systemctl enable fortnite-alert.service
sudo systemctl start fortnite-alert.service
sudo systemctl status fortnite-alert.service
If you’d rather avoid systemd entirely, a cron-based wrapper that checks once and exits (rather than looping forever) works too — swap the while True loop for a single pass and schedule it with crontab -e using */5 * * * *. You can sanity-check any cron expression at crontab.guru before committing to it.
Step 12: Add a maintenance-window pre-alert, not just an outage alert
Epic typically posts scheduled maintenance announcements on the Fortnite Status account before downtime actually starts, often naming an exact start time like “4 AM ET.” If the status API’s incident objects include a scheduled_for field (check for this during your step 1 inspection), you can add a second comparison that fires a heads-up notification as soon as a new scheduled incident appears, converted to your local time via the same to_local_time() helper from step 6. That turns this from a reactive “it’s down” tool into a proactive “it’s going down in roughly N hours” tool, which is the more useful notification for anyone trying to finish a match before the servers close.
Understanding Fortnite’s current maintenance pattern
It helps to know what “normal” looks like so your alerts make sense in context. As of Chapter 7, Season 4 (“Override,” which launched August 20, 2026), Epic has shipped updates on a broadly biweekly cadence: v42.00 on August 20, v42.10 on September 3, v42.20 on September 17, and v42.30 on October 1 alongside the Fortnitemares 2026 event. Each of those updates triggered scheduled downtime starting at 4:00 a.m. ET (8:00 a.m. UTC), with matchmaking disabled roughly 30 minutes ahead of the full maintenance window.
Not every incident is a clean, scheduled patch, though. Uptime tracker StatusGator logged a 25-minute matchmaking hiccup on September 17 and a separate, much longer outage of nearly 21 hours recorded around the same period — a reminder that unscheduled incidents can run far outside the “a couple hours” pattern that scheduled patches usually follow. That asymmetry is exactly why a script that watches for any state change, not just the ones you expect, is more useful than mentally tracking a fixed patch calendar.
| Update | Date (2026) | Scheduled start | Approx. duration |
| v42.00 (Override launch) | August 20 | 4:00 a.m. ET / 8:00 a.m. UTC | ~2-3 hours |
| v42.10 | September 3 | 4:00 a.m. ET / 8:00 a.m. UTC | ~2h 45m |
| v42.20 | September 17 | 4:00 a.m. ET / 8:00 a.m. UTC | ~2-3 hours (plus a separate unscheduled incident) |
| v42.30 (Fortnitemares 2026) | October 1 | 4:00 a.m. ET / 8:00 a.m. UTC | ~2h 30m |
Season 4 is scheduled to run through roughly October 31 or November 1, 2026, which means at least one more patch and likely an end-of-season transition are still ahead before this guide goes stale. The script doesn’t care about any of that, which is the entire point: it reacts to whatever the status feed says, whenever it says it, without you having to update a hardcoded patch calendar every two weeks.
Common pitfalls when building a status-check tool
A handful of mistakes show up repeatedly in scripts like this. Here’s what to watch for.
- Polling too aggressively. Hitting an unauthenticated public API every few seconds is a good way to get your IP rate-limited or blocked. Five minutes is plenty for a maintenance window that lasts hours.
- Hardcoding the UTC offset instead of using a real time zone. “ET is UTC-4” breaks the moment daylight saving ends. Always use
zoneinfowith a named zone likeAmerica/New_Yorkso the library handles DST transitions for you. - Not handling missing JSON keys. Status page schemas occasionally add or drop fields. Use
.get()with defaults everywhere instead of direct dictionary indexing, which raises on anything unexpected. - Alerting on every poll instead of on state change. Skip the state file and you’ll get a notification every five minutes for the entire outage, which trains you to ignore the alerts entirely.
- Treating the ntfy topic as private. Public topics on the free tier are guessable and subscribable by anyone who knows the string. Don’t put anything sensitive in the message body.
- Forgetting the script dies when the laptop sleeps. A background Python process on a laptop that goes to sleep overnight won’t catch a 4 a.m. maintenance window. Run it on something that stays powered on.
- Assuming matchmaking and login share one status. Epic’s component list separates these. A login-only outage doesn’t mean matchmaking is down, and vice versa — match your
COMPONENT_MATCHfilter carefully.
Expected output once everything is running
Here’s what a healthy log file looks like during a normal polling cycle, followed by what it looks like right as an outage starts:
2026-10-03 09:15:02 INFO Checked status: none
2026-10-03 09:20:03 INFO Checked status: none
2026-10-03 09:25:04 INFO Checked status: none
2026-10-03 09:30:02 INFO Notification sent: Fortnite status changed
2026-10-03 09:30:02 INFO Checked status: major
2026-10-03 09:35:03 INFO Checked status: major
2026-10-03 12:05:11 INFO Notification sent: Fortnite is back online
2026-10-03 12:05:11 INFO Checked status: none
On your phone, the ntfy notification for the second event would read something like: title “Fortnite is back online,” body “Epic’s status feed shows all systems operational again.” That’s the entire payoff of this project in one push notification.
Troubleshooting guide
If something isn’t working, check these in order.
- No notifications ever arrive, even during a known outage. Confirm your phone’s ntfy app is subscribed to the exact topic string in
config.py, with matching capitalization. Topic names are case-sensitive. - Script crashes with a
KeyErroron startup. The status API’s JSON shape doesn’t match what the parser expects. Re-run thecurlcommand from step 1 and compare field names against what’s infetch_status(). - Script runs but never logs anything. Check file permissions on the working directory — systemd services often run as a different user than the one who created the script files.
- Notifications arrive late, well after the servers are actually back. Your
POLL_SECONDSvalue is too high, or the status page itself updates slower than reality. Five minutes is a reasonable floor; don’t go much lower than 120 seconds. - Getting duplicate notifications for the same event. You likely have two instances of the script running at once — check with
ps aux | grep main.pyand kill the duplicate. - systemd service won’t start. Run
sudo journalctl -u fortnite-alert.service -n 50to see the actual Python traceback, which is usually a wrong file path inExecStart. - Time zone conversion looks wrong by exactly one hour. You’re probably hardcoding a UTC offset somewhere instead of using
zoneinfo, and a DST transition just happened. Search your code for any manualtimedeltahour math and replace it. ModuleNotFoundError: No module named 'requests'. Your virtual environment isn’t activated, or systemd is pointing at the system Python instead of the venv’s Python binary inExecStart.- ntfy notifications work on Wi-Fi but not on mobile data. Some carriers or VPN configurations throttle background notification delivery. Try ntfy’s “instant delivery” mode in the app settings, which uses Firebase Cloud Messaging as a fallback on Android.
Advanced tips once the basics work
Once the core loop is stable, a few extensions are worth the extra half hour.
Add a second ntfy topic tier by priority, so a full outage sends a high-priority push (which can bypass phone silent mode) while a minor degraded-performance note sends a low-priority one you can check later. ntfy supports priority levels from 1 to 5 directly in the HTTP header, so this is a one-line change to the send_notification call.
If you want a historical record rather than just the live log file, append each state change to a simple CSV instead of (or alongside) the log file, with columns for timestamp, previous state, new state, and duration since the last change. That gets you a personal uptime history without standing up a database, and you can graph it later in a spreadsheet if you’re curious how your experience compares to the official incident log.
Finally, consider running this on something that’s already always-on rather than adding a new device to your home — a NAS, an always-running home server, or a free-tier cloud instance all work. The script’s resource footprint is trivial: it sleeps for 295 out of every 300 seconds and makes one small HTTPS request otherwise.
Choosing a notification channel: ntfy vs the alternatives
ntfy.sh is used throughout this guide because it needs zero setup, but it isn’t the only option, and depending on how you already organize your notifications, a different channel might fit better. The send_notification() function from step 8 is deliberately small and self-contained, so swapping the HTTP call inside it for a different service takes a few lines, not a rewrite.
| Channel | Setup effort | Cost | Best for |
| ntfy.sh (used in this guide) | Low — pick a topic, install the app | Free on public topics | Personal phone alerts, fastest to stand up |
| Discord webhook | Medium — create a webhook URL in a server | Free | Groups who already live in a Discord server |
| Email via SMTP | Medium — app password or SMTP relay setup | Free with most providers | Alerts you don’t need instantly |
| SMS via a carrier API | Higher — third-party account and per-message cost | Usually paid per message | Alerts that must reach you with zero apps involved |
Most people building this for personal use will land on ntfy simply because it’s the fastest to get working end to end, which matters for a project meant to take under an hour. If you already run a Discord server for a Fortnite squad, though, swapping in a webhook POST means everyone in the group sees the same “servers are back” message at once instead of each person running their own copy of the script.
Running it cheaply on a Raspberry Pi
If you don’t already have a home server or a free-tier cloud account, a Raspberry Pi is the cheapest realistic always-on option for a script this light. A Raspberry Pi 4 or 5 draws somewhere around 3 to 7 watts at idle depending on peripherals, which works out to a few dollars a year in electricity even left running continuously. Installing Python 3.11+ on Raspberry Pi OS (Debian-based, so apt works normally) and following steps 2 through 11 above is identical to doing it on a regular Linux desktop, with one small difference: the systemd service file path and the Python binary path inside ExecStart need to point at wherever your venv actually lives on the Pi’s SD card or NVMe drive, not at a path copied from your main machine.
A Pi also sidesteps the laptop-sleep problem mentioned in the pitfalls section, since it has no lid to close and no aggressive power management kicking in overnight. If you’re already running a Pi for something else, like a Pi-hole DNS sinkhole or a Home Assistant instance, this script adds a negligible amount of CPU and memory overhead on top of it (the Python process idles at well under 20 MB of RAM between polls).
Backtesting your script against past incidents
Before trusting a monitoring script to wake you up at 4 a.m., it’s worth checking that your parsing logic would have caught real incidents correctly. Epic’s status page keeps a scrollable history of past incidents directly on status.epicgames.com, including the v42.00, v42.10, v42.20, and v42.30 maintenance windows referenced earlier in this guide. Open a few of those historical entries and compare the raw JSON structure (via the same curl command from step 1, run at different points if you can catch the page mid-incident) against what your fetch_status() function expects.
A simple way to stress-test this without waiting for a live outage: save a few historical JSON responses to local files during a period when you know Fortnite was down, then point fetch_status() at a local file read instead of a live request for a quick offline test pass. This catches edge cases that a single synthetic test (like the one in step 10) might miss, such as an incident object with a scheduled_for field but no resolved_at field yet, or a components list where “Fortnite” appears twice under slightly different capitalization.
Complete working project
Putting every step together, your final project folder should contain three files: config.py, main.py, and the auto-generated last_state.json and downtime_alert.log that appear after the first run. The complete main.py, combining every function from steps 5 through 9, looks like this:
import json
import os
import time
import logging
from datetime import datetime
from zoneinfo import ZoneInfo
import requests
import config
logging.basicConfig(
filename=config.LOG_FILE,
level=logging.INFO,
format="%(asctime)s %(levelname)s %(message)s",
)
def fetch_status():
response = requests.get(config.STATUS_URL, timeout=10)
response.raise_for_status()
data = response.json()
overall = data.get("status", {}).get("indicator", "unknown")
components = data.get("components", [])
fortnite_components = [
c for c in components
if config.COMPONENT_MATCH.lower() in c.get("name", "").lower()
]
return overall, fortnite_components
def to_local_time(utc_iso_string):
utc_dt = datetime.fromisoformat(utc_iso_string.replace("Z", "+00:00"))
local_dt = utc_dt.astimezone(ZoneInfo(config.LOCAL_TZ))
return local_dt.strftime("%Y-%m-%d %I:%M %p %Z")
def load_last_state():
if os.path.exists(config.STATE_FILE):
with open(config.STATE_FILE) as f:
return json.load(f)
return {"indicator": "none"}
def save_state(indicator):
with open(config.STATE_FILE, "w") as f:
json.dump({"indicator": indicator}, f)
def send_notification(title, message, priority="default"):
url = f"https://ntfy.sh/{config.NTFY_TOPIC}"
headers = {"Title": title, "Priority": priority}
try:
requests.post(url, data=message.encode("utf-8"), headers=headers, timeout=10)
logging.info("Notification sent: %s", title)
except requests.RequestException as exc:
logging.error("Failed to send notification: %s", exc)
def run():
last_state = load_last_state()
while True:
try:
overall, fortnite_components = fetch_status()
if overall != last_state.get("indicator"):
if overall == "none":
send_notification(
"Fortnite is back online",
"Epic's status feed shows all systems operational again.",
priority="high",
)
else:
detail = ", ".join(
c.get("status", "unknown") for c in fortnite_components
) or "status changed"
send_notification(
"Fortnite status changed",
f"Overall indicator: {overall}. Components: {detail}",
)
save_state(overall)
last_state["indicator"] = overall
logging.info("Checked status: %s", overall)
except requests.RequestException as exc:
logging.error("Status check failed: %s", exc)
time.sleep(config.POLL_SECONDS)
if __name__ == "__main__":
run()
Clone this structure, swap in your own time zone and ntfy topic, run the step 10 test, then deploy it under systemd. Total build time for most people following this guide start to finish lands around 40 to 50 minutes.
How this compares to just using a third-party outage tracker
Services like Downdetector and UptimeRobot are useful for a quick gut-check (“is it just me?”), and they’re worth bookmarking as a secondary source. But they’re built for breadth across thousands of services, not depth on Fortnite specifically, and none of them will text you the second your specific component of interest changes state in your specific time zone. They also tend to rely partly on user self-reports, which means a slow-ticking trickle of reports can delay the moment a real outage is confirmed on the page, versus going straight to Epic’s own authoritative feed. Building your own thin layer on top of the official source trades a few minutes of setup time for a notification system tuned exactly to what you want to know and nothing else.
Frequently asked questions
What time does Fortnite usually go down for updates?
Scheduled maintenance has consistently started at 4:00 a.m. Eastern Time (8:00 a.m. UTC) through Chapter 7 Season 4’s 2026 patch cycle, with matchmaking disabled about 30 minutes before the full window begins.
How long does Fortnite downtime usually last?
Recent scheduled updates in 2026 have run roughly 2.5 to 3 hours, based on tracking from StatusGator. Unscheduled incidents can run much longer; one was logged at close to 16 hours in September 2026.
Is Epic’s status API free to use?
Yes. The endpoint at status.epicgames.com/api is public and doesn’t require an API key or developer account. Treat it respectfully by polling every few minutes rather than every few seconds.
Do I need a server to run this script continuously?
You need something that stays powered on and connected to the internet. A desktop that sleeps won’t catch a 4 a.m. maintenance window. A Raspberry Pi, always-on home server, or a free-tier cloud VM all work well for this.
Is ntfy.sh safe to use for this?
For a low-stakes alert like “the game servers are back up,” yes. Just don’t choose a guessable topic name and don’t send anything sensitive through it, since public topics on the free tier can technically be subscribed to by anyone who knows the exact string.
Can I adapt this script for other games besides Fortnite?
Yes, as long as the game’s publisher runs a similar status page with a JSON API. Change the STATUS_URL and COMPONENT_MATCH values in config.py and the rest of the logic carries over unchanged.
Why not just follow the Fortnite Status account on social media?
That works too, and it’s a good complementary source for advance notice of scheduled maintenance. The script’s advantage is converting times to your own time zone automatically and only alerting you on the specific transition you care about, rather than every post.
What’s the next scheduled Fortnite downtime after October 1, 2026?
Chapter 7 Season 4 (“Override”) is scheduled to run through roughly October 31 or November 1, 2026, so at least one more patch and an end-of-season transition are expected before then. Exact dates aren’t published far in advance, which is exactly why a live status-watching script is more reliable than memorizing a calendar.




