Confirm this is an issue with the Python library and not an underlying OpenAI API
Describe the bug
Summary
Calling the Responses API (client.responses.parse) with an input_image whose image_url is a base64 data URI fails with HTTP 400 when the data URI string exceeds roughly 65,520 characters:
Error code: 400 - {'error': {'code': 'invalid_payload', 'message': "'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAgGBgcHBgUICAcHCQkICgwUDQwLC...' is not a valid absolute URI"}}
The same request with a smaller image succeeds. The limit applies per image_url string, not to the total request size.
The cutoff sits almost exactly on System.Uri's maximum length in .NET (0xFFF0 = 65,520), which suggests the service validates the data URI with a URI parser that enforces a length cap. Data URIs have no such length limit, and the error message describes the value as malformed rather than too long, which made this take a long time to diagnose.
Measured behaviour
Each row is one request. Images are JPEG, 1024x1448 RGB, varying only in encoded size. "URI chars" is len("data:image/jpeg;base64,") + len(b64).
| Request |
URI chars (per image) |
Result |
| Text only, no images |
n/a |
200 OK |
| 5 images |
62,087 each (310,268 total) |
200 OK |
| 1 image |
62,087 |
200 OK |
| 1 image |
63,975 |
200 OK |
| 1 image |
65,883 |
400 invalid_payload |
| 1 image |
78,427 |
400 invalid_payload |
| 1 image |
128,623 |
400 invalid_payload |
| 1 image |
196,399 |
400 invalid_payload |
| 1 image |
330,187 |
400 invalid_payload |
Accept/reject boundary is between 63,975 and 65,883 characters, bracketing 65,520.
The limit is per-image, not per-request. Five images totalling 310,268 characters are accepted, while a single 65,883-character image is rejected. Splitting a batch into more requests therefore does not help; only shrinking each individual image does.
Reproduction
import base64
from io import BytesIO
from azure.ai.projects.aio import AIProjectClient
from azure.identity.aio import DefaultAzureCredential
from PIL import Image
from pydantic import BaseModel
class Result(BaseModel):
label: str
def make_image_b64(noise_alpha: float) -> str:
"""1024x1448 JPEG. Higher noise_alpha -> larger encoded size."""
noise = Image.effect_noise((1024, 1448), 64.0)
speckle = Image.merge("RGB", (noise, noise, noise))
base = Image.new("RGB", (1024, 1448), color="white")
image = Image.blend(base, speckle, noise_alpha)
with BytesIO() as buffered:
image.save(buffered, format="JPEG")
return base64.b64encode(buffered.getvalue()).decode("utf-8")
async def main():
async with DefaultAzureCredential() as credential:
async with AIProjectClient(credential=credential, endpoint="<project-endpoint>") as project:
async with project.get_openai_client() as client:
for alpha in (0.0, 0.06, 1.0): # ~62k, ~66k, ~1M URI chars
b64 = make_image_b64(alpha)
uri = f"data:image/jpeg;base64,{b64}"
print(f"uri chars = {len(uri)}")
try:
await client.responses.parse(
model="<deployment-name>",
instructions="Describe the image.",
input=[
{
"role": "user",
"content": [
{"type": "input_text", "text": "Describe this:"},
{"type": "input_image", "image_url": uri},
],
}
],
text_format=Result,
reasoning={"effort": "low"},
)
print(" -> accepted")
except Exception as e:
print(f" -> {e}")
Output:
uri chars = 62087
-> accepted
uri chars = 65883
-> Error code: 400 - {'error': {'code': 'invalid_payload', 'message': "'data:image/jpeg;base64,...' is not a valid absolute URI"}}
uri chars = 1035135
-> Error code: 400 - {'error': {'code': 'invalid_payload', 'message': "'data:image/jpeg;base64,...' is not a valid absolute URI"}}
Expected behaviour
A valid base64 data URI should be accepted regardless of length, up to the documented request/image size limits for the model. If a length cap is intentional, it should be documented and the error should state that the image exceeds the maximum size rather than reporting the value as not a valid URI.
Impact
This makes base64 image input unusable at any realistic document resolution. A single page of a scanned PDF rendered at 300 DPI / 1024x1448 encodes to roughly 440,000 base64 characters, about 6.7x over the limit. To fit under 65,520 characters the same page has to be rendered at roughly 340x481, which is too low a resolution for document classification and OCR-adjacent tasks.
Because the error names the value as malformed rather than oversized, and because the same code path works for small images, this presents as an intermittent "some documents fail" bug in production rather than a size limit.
Environment
openai 2.34.0
azure-ai-projects 2.1.0
azure-identity 1.25.3
- Python 3.13.11, Linux
- Client obtained via
AIProjectClient.get_openai_client()
- Endpoint: Azure AI Foundry project endpoint
- API: Responses API,
client.responses.parse with text_format (structured outputs) and reasoning={"effort": "low"}
Related
- #46305 — also
invalid_payload on base64 image input to the Responses API, but with a different message (The provided data does not match the expected schema) and no length component. Closed as addressed. This report is a distinct failure mode: valid, well-formed data URIs rejected purely on length.
Notes
- Reproduced consistently across many requests; not intermittent.
- Only the image size varies between the passing and failing requests. Message structure, deployment, schema,
reasoning, and client construction are identical.
- Not an SDK-side validation failure: the SDK serialises the string unchanged and the rejection comes back from the service as an HTTP 400.
To Reproduce
Reproduction
import base64
from io import BytesIO
from azure.ai.projects.aio import AIProjectClient
from azure.identity.aio import DefaultAzureCredential
from PIL import Image
from pydantic import BaseModel
class Result(BaseModel):
label: str
def make_image_b64(noise_alpha: float) -> str:
"""1024x1448 JPEG. Higher noise_alpha -> larger encoded size."""
noise = Image.effect_noise((1024, 1448), 64.0)
speckle = Image.merge("RGB", (noise, noise, noise))
base = Image.new("RGB", (1024, 1448), color="white")
image = Image.blend(base, speckle, noise_alpha)
with BytesIO() as buffered:
image.save(buffered, format="JPEG")
return base64.b64encode(buffered.getvalue()).decode("utf-8")
async def main():
async with DefaultAzureCredential() as credential:
async with AIProjectClient(credential=credential, endpoint="<project-endpoint>") as project:
async with project.get_openai_client() as client:
for alpha in (0.0, 0.06, 1.0): # ~62k, ~66k, ~1M URI chars
b64 = make_image_b64(alpha)
uri = f"data:image/jpeg;base64,{b64}"
print(f"uri chars = {len(uri)}")
try:
await client.responses.parse(
model="<deployment-name>",
instructions="Describe the image.",
input=[
{
"role": "user",
"content": [
{"type": "input_text", "text": "Describe this:"},
{"type": "input_image", "image_url": uri},
],
}
],
text_format=Result,
reasoning={"effort": "low"},
)
print(" -> accepted")
except Exception as e:
print(f" -> {e}")
Code snippets
OS
Linux
Python version
Python 3.13.11
Library version
2.34.0
Confirm this is an issue with the Python library and not an underlying OpenAI API
Describe the bug
Summary
Calling the Responses API (
client.responses.parse) with aninput_imagewhoseimage_urlis a base64 data URI fails with HTTP 400 when the data URI string exceeds roughly 65,520 characters:The same request with a smaller image succeeds. The limit applies per
image_urlstring, not to the total request size.The cutoff sits almost exactly on
System.Uri's maximum length in .NET (0xFFF0= 65,520), which suggests the service validates the data URI with a URI parser that enforces a length cap. Data URIs have no such length limit, and the error message describes the value as malformed rather than too long, which made this take a long time to diagnose.Measured behaviour
Each row is one request. Images are JPEG, 1024x1448 RGB, varying only in encoded size. "URI chars" is
len("data:image/jpeg;base64,") + len(b64).invalid_payloadinvalid_payloadinvalid_payloadinvalid_payloadinvalid_payloadAccept/reject boundary is between 63,975 and 65,883 characters, bracketing 65,520.
The limit is per-image, not per-request. Five images totalling 310,268 characters are accepted, while a single 65,883-character image is rejected. Splitting a batch into more requests therefore does not help; only shrinking each individual image does.
Reproduction
Output:
Expected behaviour
A valid base64 data URI should be accepted regardless of length, up to the documented request/image size limits for the model. If a length cap is intentional, it should be documented and the error should state that the image exceeds the maximum size rather than reporting the value as not a valid URI.
Impact
This makes base64 image input unusable at any realistic document resolution. A single page of a scanned PDF rendered at 300 DPI / 1024x1448 encodes to roughly 440,000 base64 characters, about 6.7x over the limit. To fit under 65,520 characters the same page has to be rendered at roughly 340x481, which is too low a resolution for document classification and OCR-adjacent tasks.
Because the error names the value as malformed rather than oversized, and because the same code path works for small images, this presents as an intermittent "some documents fail" bug in production rather than a size limit.
Environment
openai2.34.0azure-ai-projects2.1.0azure-identity1.25.3AIProjectClient.get_openai_client()client.responses.parsewithtext_format(structured outputs) andreasoning={"effort": "low"}Related
invalid_payloadon base64 image input to the Responses API, but with a different message (The provided data does not match the expected schema) and no length component. Closed as addressed. This report is a distinct failure mode: valid, well-formed data URIs rejected purely on length.Notes
reasoning, and client construction are identical.To Reproduce
Reproduction
Code snippets
OS
Linux
Python version
Python 3.13.11
Library version
2.34.0