HTTP 503 Service Unavailable: What It Means and How to Fix It
HTTP 503 Service Unavailable is a status code meaning the server cannot handle the request right now because of temporary overload or scheduled maintenance, and the condition will likely clear after a delay. The server may send a Retry-After header saying when to try again, which well-behaved clients and crawlers should honor before retrying.
- Code
- 503
- Name
- Service Unavailable
- Class
- 5xx server error
- Retry?
- Yes, with backoff
What causes a 503 error?
- →Planned maintenance or a deploy that takes the service offline.
- →Traffic above capacity, including traffic from aggressive crawlers.
- →An autoscaler that has not caught up yet.
- →A load balancer with no healthy backends.
How do you fix a 503 error when web scraping?
- →Honor
Retry-Afterwhen it is present, and back off exponentially when it is not. - →Lower your request rate. If your crawler is part of the load, retries make it worse.
- →Schedule large crawls outside the site’s peak hours.
How do you fix a 503 error on your own server?
- →Send
Retry-Afterduring maintenance so crawlers come back at the right time. - →Return 503 rather than 200 on maintenance pages, so search engines do not index the maintenance text.
- →Shed load early with rate limits (429) before the whole service tips into 503s.
How do you handle a 503 error in a retry loop?
fetch() treats 503 as temporary. It waits for Retry-After when the server sends a number of seconds, otherwise backs off exponentially with jitter, caps every wait at 60 seconds, and gives up after five attempts.
import random
import time
import requests
RETRYABLE = {408, 429, 500, 502, 503, 504, 520, 521, 522, 523, 524}
def fetch(url: str, max_attempts: int = 5) -> requests.Response:
for attempt in range(max_attempts):
try:
response = requests.get(url, timeout=(10, 60))
except requests.Timeout:
time.sleep(2**attempt + random.uniform(0, 1))
continue
if response.status_code not in RETRYABLE:
response.raise_for_status()
return response
retry_after = response.headers.get("Retry-After", "")
backoff = 2**attempt + random.uniform(0, 1)
time.sleep(min(int(retry_after) if retry_after.isdigit() else backoff, 60))
raise RuntimeError(f"Gave up on {url} after {max_attempts} attempts")
How does Context.dev handle a 503 error?
Context.dev retries the fetch for you, and by default Scrape can reuse a capture made in the last 3 days (maxAgeMs), so a page that is briefly down may still come back from cache. If no capture is available, the failed output carries an error_code and message inside an HTTP 200 response, and a request where every output fails is not charged. The Context.dev SDKs retry twice with exponential backoff after connection errors and 408, 409, 429, and 5xx responses from the API itself.
See what the web scraping API does on every request, or read how to fix HTTP errors in web scraping for a longer walkthrough.
Frequently asked questions about a 503 error
What does 503 Service Unavailable mean?
The server is up but cannot take requests right now, usually because of overload or maintenance. It expects to recover.
How long does a 503 error last?
From seconds to hours. Check Retry-After for the server’s own estimate, and the site’s status page for maintenance windows.
Does a 503 hurt SEO?
A short 503 during maintenance is the recommended signal and does not hurt rankings. Long-running 503s can lead search engines to drop pages.
Which status codes are related to 503?
Sources
Last reviewed