N8n HTTP Request: JSON parameter invalid when injecting dynamic variables into Browserless API call

The problem

Note: I usually use the community node Browserless, but for this specific case I have to call the API directly via an HTTP Request node.

I want to execute a Playwright script on browserless from n8n by sending:

  1. My JavaScript (Playwright) code
  2. A context containing dynamic variables (postUrl, userAgent, extraHeaders, seedCookieList, timeoutMs, etc.)

Working Case (Hardcoded)

When I use hardcoded variable, everything works fine

{
  "code": "export default async function (...) { /* … */ }",
  "context": {
    "postUrl": "https://example.com/",
    "userAgent": "Mozilla/...",
    "extraHeaders": { "accept-language": "fr-FR,..." },
    "seedCookieList": [ /* static array */ ],
    "timeoutMs": 45000
  }
}

Problem with Dynamic Variables

As soon as I use the {{ ... }} syntax in the jsonBody to inject data from a Set node or other nodes, I always get:

{
  "errorMessage": "JSON parameter needs to be valid JSON",
  "errorDetails": {},
  "n8nDetails": { /* … */ }
}

The generated JSON is either truncated or invalid (the seedCookieList array disappears or becomes corrupted, like “Object Object” ), even though the Set node’s output contains a valid array.

Exact Error Message

NodeOperationError: JSON parameter needs to be valid JSON

Minimal Workflow to Reproduce

I’ve simplified my node as much as possible. The original contained a very complex script plus private data (personal cookies). This minimal example should give a clear idea of what I’m trying to do.

Feel free to replace the URL with your own browserless endpoint and insert your token. The “Simple Code with Dynamic Variables” node works correctly.

Output of the HTTP Request Node

{
  "errorMessage": "JSON parameter needs to be valid JSON",
  "errorDetails": {},
  "n8nDetails": {
    "nodeName": "FINAL5",
    "nodeType": "n8n-nodes-base.httpRequest",
    "nodeVersion": 4.2,
    "itemIndex": 0,
    "time": "05/08/2025 19:21:07",
    "n8nVersion": "1.101.2 (Self Hosted)",
    "binaryDataMode": "default",
    "stackTrace": [
      "NodeOperationError: JSON parameter needs to be valid JSON",
      "    at ExecuteContext.execute (/usr/local/lib/node_modules/n8n/node_modules/.pnpm/n8n-nodes-base@file+packages+nodes-base_@[email protected]_asn1.js@5_1af219c3f47f2a1223ec4ccec249a974/node_modules/n8n-nodes-base/nodes/HttpRequest/V3/HttpRequestV3.node.ts:366:15)",
      "    at WorkflowExecute.runNode (/usr/local/lib/node_modules/n8n/node_modules/.pnpm/n8n-core@[email protected][email protected][email protected][email protected]_/node_modules/n8n-core/src/execution-engine/workflow-execute.ts:1194:32)",
      "    at /usr/local/lib/node_modules/n8n/node_modules/.pnpm/n8n-core@[email protected][email protected][email protected][email protected]_/node_modules/n8n-core/src/execution-engine/workflow-execute.ts:1564:38",
      "    at processTicksAndRejections (node:internal/process/task_queues:105:5)",
      "    at /usr/local/lib/node_modules/n8n/node_modules/.pnpm/n8n-core@[email protected][email protected][email protected][email protected]_/node_modules/n8n-core/src/execution-engine/workflow-execute.ts:2135:11"
    ]
  }
}

n8n Environment

  • Version: 1.101.2 (Self Hosted)
  • Database: Postgres
  • EXECUTIONS_PROCESS: own
  • Running via: npm (self‑hosted)
  • OS: Ubuntu 22.04 LTS

Context: I must use an HTTP Request because the Browserless node doesn’t fit this use case. My goal is to pass a moderately complex script and dynamic variables (including a cookie array). The JSON body breaks as soon as I add those dynamic variables via {{ … }}, invalidating the JSON and preventing execution.

Objective: Understand why the dynamic variable (array) isn’t inserted correctly and how to build the jsonBody so it remains valid JSON. Any help is appreciated! Cheers :tada:

Hey @Khalagan, hope all is well.

In the middle node, the JSON starts with =, right off the bat this is an invalid JSON.

{{ {
  code: `
export default async function ({ page, item, context }) {
  const c = context || {};
  const postUrl = (item?.json?.url || c.postUrl || '').trim();
  await page.setUserAgent(c.userAgent);
  await page.setExtraHTTPHeaders(c.extraHeaders);
  await page.goto(postUrl, { waitUntil: 'domcontentloaded', timeout: c.timeoutMs });
  // … votre gros script ici …
  return { type: 'application/json', data: { ok: true } };
}
  `.trim(),
  context: {
    postUrl:       $json.url,
    userAgent:     $json.user_agent,
    extraHeaders:  { 'accept-language': 'fr-FR,fr;q=0.9,en;q=0.8' },
    seedCookieList: $items('Exemple Variables1')[0].json.cookie_list || [],
    timeoutMs:     $json.timeoutMs || 45000,
    cutoffDays:    $json.cutoffDays || 7
  }
}.toJsonString() }}

this probably would work.

The bottom JSON is invalid as it contains a JS object with newlines, which makes it invalid.

{
  "code": "export default async function ({ page, item, context }) {\n  const { postUrl, userAgent, extraHeaders, seedCookieList, timeoutMs } = context;\n  await page.setUserAgent(userAgent);\n  await page.setExtraHTTPHeaders(extraHeaders);\n  await page.goto(postUrl, { waitUntil: 'domcontentloaded', timeout: timeoutMs });\n  // … votre script ici …\n  return { type: 'application/json', data: { ok: true } };\n}",
  "context": {{ 
    $json.context || {
      postUrl:        $items("Exemple Variables1")[0].json.url || $json.url || "",
      userAgent:      $json.user_agent || "Mozilla/5.0 (Windows NT 10.0; Win64; x64)",
      extraHeaders:   { "accept-language": "fr-FR,fr;q=0.9,en;q=0.8" },
      seedCookieList: $items("Exemple Variables1")[0].json.cookie_list || [],
      timeoutMs:      $json.timeoutMs   || 45000,
      cutoffDays:     $json.cutoffDays  || 7
    }.toJsonString()
  }}
}

This would probably make it valid.

Hey Jabbsons, thanks a lot for your quick reply!

I posted that message on the forum because I had a feeling the issue was something simple, but I’m still not used to working with JavaScript inside an HTTP Request node in n8n. Honestly, I was pretty tired yesterday and out of ideas :sweat_smile:

Today, with a clearer head, I tried a different approach:

  • I moved the script and dynamic context variables into a Function node right before the HTTP Request.
  • Then I passed them properly into the request body.

Just like yesterday, I first got the classic [object Object], but this time, after applying JSON.stringify(), it magically worked :upside_down_face:

Lesson learned:
When you’re dealing with JS in a JSON (especially in a jsonBody), it’s way safer to:

  1. Pre-process everything in a Function or Code node (treat n8n like a beginner with JSON).
  2. Always double-check that what you inject is a string (when needed), not a raw object.

Thanks again for your time and help — and maybe see you around (hopefully not because of another bug :grinning_face_with_smiling_eyes:).

3 Likes

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.