Why does your API work in curl but fail in a browser agent?
Diagnose browser CORS failures with origin and preflight evidence while keeping authentication and permitted origins explicit.
A request succeeds in curl, but code running in a browser reports a CORS error. Both observations can be correct. The server may return the data while the browser refuses to expose the response to the calling page.
For an agent integration, first identify where the request runs. Browser page JavaScript, an extension and a remote server may use different request paths and security contexts. Diagnose the supported client's actual behavior before changing headers.
Identify the origin that needs access
CORS lets a server indicate which other origins a browser should permit to access a resource. An origin includes the scheme, host and port. A page at https://app.example.com fetching https://api.example.com makes a cross-origin request even though the hostnames share a parent domain. MDN describes this browser enforcement and the preflight mechanism in its CORS guide.
Write down the calling page's origin and the requested URL from browser developer tools. Do not substitute the name of the AI company for the origin the browser actually sends. An agent operating your own page may make requests from that page's origin.
Command-line success is useful evidence that the endpoint answered that request. It does not test whether browser JavaScript from another origin may read the result. Keep those findings separate in the issue report.
Inspect the preflight and the actual response
For some requests, the browser first sends OPTIONS with the intended method and request headers. Your gateway must let the CORS policy evaluate that request. An application that handles the eventual POST correctly can still fail earlier in middleware.
Use a read endpoint or a sandbox while investigating. This command illustrates a preflight for a hypothetical authenticated read:
curl -i -X OPTIONS https://api.example.com/projects \
-H 'Origin: https://app.example.com' \
-H 'Access-Control-Request-Method: GET' \
-H 'Access-Control-Request-Headers: authorization'
The command does not reproduce browser enforcement. It lets you inspect what the server returns for the stated preflight. Compare it with the real browser's network record, including redirects and any gateway error body.
Check the actual response as well. Passing preflight is insufficient if the response the browser finally receives lacks the required access headers. Include error paths in that inspection so an authentication refusal does not become an opaque CORS failure to the client.
Choose an explicit sharing policy
For a public resource without credentials, a wildcard origin can be appropriate. For credentialed requests, the wildcard is not valid: the server must return the allowed requesting origin. MDN's Access-Control-Allow-Origin reference documents that distinction.
Avoid reflecting any received origin unconditionally. Maintain the set of origins your application intends to support, then compare the request against that policy. Keep development origins separate from production configuration so a temporary local experiment does not accidentally become a permanent permission.
If the response changes according to the request origin, account for that in caching. MDN explains using Vary: Origin for responses that select a specific allowed origin. Check the public CDN response rather than inspecting only the application's local headers. Origin response examples.
Keep authorization on the server
CORS controls whether browser code can share a response across origins. It does not replace the endpoint's account permissions. A request from an allowed origin still needs valid authorization to read private data. A server client is not made safe by the absence of browser permission.
Keep the API's own identity and permission checks intact. When a browser request uses cookies, review the supported credential behavior as part of that integration. Do not change unrelated cookie settings solely because the console mentions CORS; inspect the actual request first.
For requests that change records, verify outcome before retrying. A browser's inability to read a response does not by itself establish that the server did nothing. Use a sandbox record and a lookup path to investigate uncertain writes.
Make the fix reviewable
Save the failing origin, method and requested headers. After the change, repeat the same request from an allowed origin and a deliberately disallowed one. Confirm that the former works and the latter does not receive access. Repeat an authentication error as well as a success.
Keep the browser network record with the issue. Include the failed preflight or response, the origin that requested it and the policy that should have allowed or rejected it.
Close the issue with the supported client context and the tested origins. "Works in a browser" is too broad to serve as a regression check.