t4mer@notebook

// article · http · laravel · 9 may 2026 · 2 min

Why Postman and Laravel can send “the same request” and get different results

Headers, encodings, and the dangerous comfort of a green Postman screenshot.

This is a genre of bug, not a single incident. I have hit it enough times that I now treat “but it works in Postman” as a smell, not as evidence.

The pattern:

  1. Provider documentation.
  2. Postman collection, often from the provider.
  3. Green 200.
  4. Same URL from Laravel Http:: or Guzzle. 401, 400, 421, or a body that looks like XML pretending to be JSON.

Then the meeting where somebody pastes the Postman screenshot as if the application is being difficult on purpose.

Postman is also a client

Postman is not a transparent window onto the network. It has opinions:

  • it may send Content-Type and Accept you did not notice
  • it may follow redirects
  • it may decompress
  • it may persist cookies
  • it may apply a collection-level header
  • it may send a bearer token from an environment you forgot was selected

Laravel will send what you wrote. That is the whole difference.

The list I walk before inventing a conspiracy

Content-Type. Postman said JSON. The server wanted application/x-www-form-urlencoded. Or the opposite.

Accept. You asked for JSON in Postman. Laravel sent */* or nothing, and the server answered with HTML. Related: Laravel returning HTML instead of JSON.

Authorization. “Bearer” with a space. A token with a newline copied from Slack.

Host. You should almost never set this by hand. Related: HTTP 421.

JSON encoding of empty objects and []. PHP’s json_encode and JavaScript’s JSON.stringify are not spiritually aligned.

A method that has saved me hours

Do not compare screenshots. Compare raw requests.

  • Postman: Console, look at the actual request.
  • Laravel: Http::dd() / Guzzle middleware / a local proxy.

If you cannot diff the bytes, you are arguing with a feeling.

The runbook: API works in Postman but fails in Laravel.

The lesson I repeat to myself

APIs do not care that your Postman collection is the official one. They care about the request that arrived. Laravel is not broken because it is more literal than a GUI. Literal is the job.