xtekky/gpt4free · error · ResponseStatusError
Response {response.status}: {'HTML content' if is_html else
Error message
Response {response.status}: {'HTML content' if is_html else message} What it means
The fallback branch of g4f's async raise_for_status: any non-ok status that is not 429/402/401/403-with-known-fingerprint/502/504/400-bad-key becomes ResponseStatusError. When the body is HTML the message is the literal 'HTML content' instead of the page, so huge challenge/error pages don't leak into exceptions.
Source
Thrown at g4f/requests/raise_for_status.py:83
if message is None or is_html:
if response.status == 520:
message = "Unknown error (Cloudflare)"
if response.status in (429, 402):
raise RateLimitError(f"Response {response.status}: {message}")
if response.status == 401:
raise MissingAuthError(f"Response {response.status}: {message}")
if response.status == 403 and is_cloudflare(message):
raise CloudflareError(f"Response {response.status}: Cloudflare detected")
elif response.status == 403 and (is_openai(message) or is_lmarena(message)):
raise MissingAuthError(f"Response {response.status}: OpenAI Bot detected")
elif response.status == 502:
raise ResponseStatusError(f"Response {response.status}: Bad Gateway")
elif response.status == 504:
raise RateLimitError(f"Response {response.status}: Gateway Timeout ")
elif response.status == 400 and "API key not valid" in message:
raise MissingAuthError(f"Response {response.status}: Invalid API key")
else:
raise ResponseStatusError(
f"Response {response.status}: {'HTML content' if is_html else message}"
)
def raise_for_status(
response: Union[Response, StreamResponse, ClientResponse, RequestsResponse],
message: str = None,
):
if hasattr(response, "status"):
return raise_for_status_async(response, message)
if response.ok:
return
is_html = False
if message is None:
is_html = response.headers.get("content-type", "").startswith(
"text/html"
) or response.text.startswith("<!DOCTYPE")
message = response.textView on GitHub (pinned to 973504e177)
Solutions
- Read the numeric status in the message ('Response {status}: ...') to identify the real cause.
- For 404/400: update g4f (pip install -U g4f) — provider endpoints and payloads change often.
- For 5xx: retry later or switch provider.
- For 400: validate the model name and message format against the provider's current API.
Defensive patterns
Strategy: try-catch
Type guard
from g4f.errors import ResponseStatusError, CloudflareError, RateLimitError
def is_generic_status(err: BaseException) -> bool:
return isinstance(err, ResponseStatusError) and not isinstance(err, (CloudflareError, RateLimitError)) Try / catch
from g4f.errors import ResponseStatusError
try:
result = await client.chat.completions.async_create(...)
except ResponseStatusError as e:
status = int(str(e).split(':')[0].split()[-1])
if status >= 500:
result = await retry_later()
elif status in (400, 404):
raise RuntimeError(f'Provider API mismatch: {e}') from e
else:
raise Prevention
- Parse the embedded status code to route handling
- Pin and regularly update g4f to track provider API changes
- Retry only 5xx; fix payload on 400; update g4f on 404
- Log the full message once — 'HTML content' still hides the actual status
When it happens
Trigger: Statuses like 400 (other validation errors), 404 (dead provider endpoint), 405, 408, 418, 500, 501, 503, or any HTML error page not matching the Cloudflare/OpenAI fingerprints.
Common situations: Provider changed its URL/API shape (404); upstream 500 crash; request payload rejected with 400 (bad model name, malformed messages); unmaintained provider in an old g4f version.
Related errors
- Response {response.status_code}: {'HTML content' if is_html
- Response {response.status}: {message}
- Response {response.status}: Cloudflare detected
- Response {response.status}: OpenAI Bot detected
- Response {response.status}: Bad Gateway
AI-assisted analysis of xtekky/gpt4free@973504e177 (2026-08-14).
Data as JSON: /api/errors/b045b90684f720a9.
Report an issue: GitHub.