Hey everyone,
I’m trying to automate logging into a website (signin.crmls.org) using the HTTP Request node in n8n (v1.90.2 Cloud). The goal is to perform a POST request to the login endpoint, handle redirects, and establish an authenticated session for subsequent steps (like searching for records).
I’ve analyzed the successful browser login request using developer tools and have a HAR log. It shows a standard POST request with Content-Type: application/x-www-form-urlencoded, including form parameters like Username, Password, and a dynamic __RequestVerificationToken. The successful flow involves a few 302 redirects.
My n8n workflow currently does the following:
-
HTTP Request (GET Login Page): Fetches the initial login page to get the HTML.
-
HTML Extract: Parses the HTML to extract the __RequestVerificationToken value from a hidden input field.
-
HTTP Request (POST Login): Attempts to send the login credentials and the extracted token.
However, this POST request consistently results in a 400 Bad Request error from the server.
Here is the relevant request data from my browser’s HAR log for the successful POST login:
{
"method": "POST",
"url": "https://signin.crmls.org/Account/Login?ReturnUrl=%2Fconnect%2Fauthorize%2Fcallback%3Fclient_id%3DmemberPortalUI%26redirect_uri%3Dhttps%253A%252F%252Fmember.recenterhub.com%252Fcallback%26response_type%3Dcode%26scope%3DODataApi%2520openid%2520CrmlsProfile%2520MemberPortalApi%2520offline_access%26state%3Df4e7a2625fc949108fb119e54c11c092%26code_challenge%3DsyCjb-UqfUFShJmkLmMNTKuIsM1TTY0YHN-SUwshju4%26code_challenge_method%3DS256%26response_mode%3Dquery",
"httpVersion": "http/2.0",
"headers": [
{ "name": "accept", "value": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7" },
{ "name": "accept-encoding", "value": "gzip, deflate, br, zstd" },
{ "name": "accept-language", "value": "en-US,en;q=0.9" },
{ "name": "cache-control", "value": "no-cache" },
{ "name": "content-type", "value": "application/x-www-form-urlencoded" },
{ "name": "origin", "value": "null" },
{ "name": "pragma", "value": "no-cache" },
{ "name": "priority", "value": "u=0, i" },
{ "name": "referer", "value": "https://signin.crmls.org/Account/Login?ReturnUrl=..." /* Full ReturnUrl from GET page URL */},
{ "name": "sec-ch-ua", "value": "\"Not(A:Brand\";v=\"99\", \"Opera\";v=\"118\", \"Chromium\";v=\"133\"" },
{ "name": "sec-ch-ua-mobile", "value": "?0" },
{ "name": "sec-ch-ua-platform", "value": "\"Windows\"" },
{ "name": "sec-fetch-dest", "value": "document" },
{ "name": "sec-fetch-mode", "value": "navigate" },
{ "name": "sec-fetch-site", "value": "same-origin" },
{ "name": "sec-fetch-user", "value": "?1" },
{ "name": "upgrade-insecure-requests", "value": "1" },
{ "name": "user-agent", "value": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36 OPR/118.0.0.0" }
],
"postData": {
"mimeType": "application/x-www-form-urlencoded",
"text": "ReturnUrl=/* value */&LayoutLogo=/* value */&LoginLogo=/* value */&Username=[YOUR_ACTUAL_USERNAME]&Password=[YOUR_ACTUAL_PASSWORD]&button=login&__RequestVerificationToken=[THE_TOKEN_VALUE]",
"params": [
{ "name": "ReturnUrl", "value": "/* value */" }, // Note: ReturnUrl appears twice in the raw text, but only once here. Add it twice in n8n Body Parameters.
{ "name": "LayoutLogo", "value": "/* value */" },
{ "name": "LoginLogo", "value": "/* value */" },
{ "name": "Username", "value": "[YOUR_ACTUAL_USERNAME]" },
{ "name": "Password", "value": "[YOUR_ACTUAL_PASSWORD]" },
{ "name": "button", "value": "login" },
{ "name": "__RequestVerificationToken", "value": "[THE_TOKEN_VALUE]" }
]
}
}
(Note: I’ve replaced sensitive data and some long values with placeholders like /* value */ or [YOUR_ACTUAL_USERNAME] to keep the post concise and secure. In n8n I’m using literal values or expressions for testing).
In my n8n HTTP Request node configuration for the POST login, I have:
-
Method: POST
-
URL: The full URL from the HAR
-
Body Content Type: Form Urlencoded
-
Body Parameters: Added all the listed parameters (ReturnUrl twice, LayoutLogo, LoginLogo, Username, Password, button, __RequestVerificationToken) with values matching the HAR (Username/Password are literal for testing, Token is from the previous HTML Extract node).
-
Headers: Added all the headers listed in the HAR (Accept, Accept-Language, Cache-Control, Origin, Pragma, Referer, sec-ch-*, Upgrade-Insecure-Requests, User-Agent). I did not manually add Content-Type as selecting “Form Urlencoded” should handle this.
However, the node fails with this error:
{
"errorMessage": "Bad request - please check your parameters",
"errorDescription": "400 - \"\"",
"errorDetails": {
"rawErrorMessage": [
"400 - \"\""
],
"httpCode": "400"
}
}
IGNORE_WHEN_COPYING_START
content_copy download
Use code with caution. Json
IGNORE_WHEN_COPYING_END
(I’ve removed the n8nDetails and stackTrace to keep the post short and within limits).
I’ve checked the “Request” tab in the n8n node’s output after execution, and it appears to be sending a request very similar to the one in the HAR, specifically:
Ok, I wanted to add the execution request history here, but when I go to the execution and click on the http node there is no request tab!!!! So I cannot copy and paste the http node or the request it makes! If you know how I can get that I appreciate it!!
Despite the apparent similarity, the server rejects it.
My questions are:
1. Given the detailed HAR comparison and the persistent 400, are there any other common pitfalls or subtle differences I might be missing when replicating a browser POST login?
2. Is there a way to get an even more raw view of the request sent by the n8n HTTP Request node, including the exact byte stream, to compare it definitively against the HAR's raw postData.text?
3. Could this indicate the website is using client-side JavaScript checks or other browser-specific validation that makes the HTTP Request approach infeasible?
Any insights or debugging tips would be greatly appreciated!
Thank you!