Hi everyone,
I’m facing a strange issue with n8n HTTP Request.
Environment
n8n Self Hosted 2.20.11
HTTP Request node v4.4
External API using JWT Bearer authentication
What happens
I call the API Authorization endpoint from n8n.
The API returns a valid JWT token.
I use that exact token in a second HTTP Request node.
The API responds with:
{
“result”: “error”,
“description”: “No valid key”
}
HTTP status: 401
Important
The same token copied manually from n8n into Postman works correctly.
The API provider has verified the endpoint and credentials.
The exact cURL exported from Postman was imported into a brand-new HTTP Request node and still fails in n8n.
Lowercase Headers option tested.
Gzip / compression settings tested.
Accept-Encoding: identity tested.
Authorization header is sent as:
Authorization: Bearer
The API vendor tested the same request from Postman with the same token and receives:
{
“result”: “ok”,
“idlead”: “5”
}
Has anyone seen a case where n8n sends something differently than Postman even when importing the exact cURL?
Any ideas on how to inspect the raw outgoing request from n8n would be appreciated.
Thanks.
@Hector_AnVa fastest way to see what n8n actually sends (exactly what you asked): point both at a request inspector. grab a webhook.site url, set the n8n node AND your Postman request to hit it, fire both, diff the captured headers. that always exposes the difference.
youve ruled out casing/gzip, so the two usual culprits:
duplicate Authorization. if the nodes Authentication is set to a credential AND theres also a manual Authorization header (the cURL import often adds one), n8n sends two and the api 401s, keep exactly one.
n8ns default headers, it adds a User-Agent and sometimes Accept-Encoding that Postman doesnt, and strict gateways reject on those.
since even the imported cURL fails, my moneys on the double Authorization, the webhook.site diff confirms it in 30 seconds.
To see exactly what n8n is sending, use a request inspection service. This is the most reliable way to compare the n8n request against the Postman request.
Go to Webhook.site and copy the unique URL provided.
Change your second HTTP Request node’s URL to this Webhook.site URL.
Execute the node.
Inspect the headers and body in the Webhook.site interface.
What to look for: Check if Authorization is being double-encoded, if extra whitespace is present, or if the Content-Type is different than what your API expects.
n8n’s “Authentication: Predefined Credential Type” can sometimes add headers that conflict with your manually added Authorization header. Ensure you aren’t accidentally sending twoAuthorization headers.
Test: Set the Authentication dropdown to “None” and strictly use a Header parameter named Authorization with the value Bearer <TOKEN>.
If you are passing the token via an expression (e.g., {{ $json.token }}), ensure there are no trailing newlines or hidden spaces being captured from the previous node. Try trimming it: {{ $json.token.trim() }}.
Some APIs block requests based on the default axios User-Agent header (often axios/x.x.x). Try adding a custom User-Agent header (e.g., Mozilla/5.0...) to mimic a browser.
Ensure the Accept header is explicitly set (e.g., application/json), as some APIs behave differently if the default */* is sent.
Building on @kjooleng’s Webhook.site tip: A very common cause of exactly this pattern (token works in Postman, identical token fails in n8n) is an invisible whitespace or line break at the end of the token that gets inserted when copying from the first HTTP response into n8n.
Specifically to check: In the first HTTP Request node that returns the JWT, look at the output carefully, preferably via the Code node using JSON.stringify($json.token) instead of the normal view. If "\n" or extra spaces appear at the end there, that’s the cause. Postman often trims automatically when you manually paste, n8n doesn’t.
The fix would then be to add a .trim() to the token field before passing it to the second request, either via a Code node or directly in the Expression field: {{ $json.token.trim() }}.