Zie619/n8n-workflows · error · Error

HTML body is undefined. Check the previous node's output.

Error message

HTML body is undefined. Check the previous node's output.

What it means

Thrown by the 'Scrape raw video URL' Code node in a TikTok video-download workflow. The node expects the previous HTTP Request node to expose the page HTML under json.data. When that field is undefined (request failed, response shape differs, or the HTTP node put the body under a different key), the guard fires before any regex scraping happens.

Source

Thrown at workflows/Code/1802_Code_Manual_Import_Webhook.json:76

              "name": "User-Agent",
              "value": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/91.0.4472.124"
            }
          ]
        }
      },
      "typeVersion": 4.2,
      "notes": "This httpRequest node performs automated tasks as part of the workflow."
    },
    {
      "id": "734a5304-f67f-4ace-a1da-0d268664452c",
      "name": "Scrape raw video URL",
      "type": "n8n-nodes-base.code",
      "position": [
        480,
        20
      ],
      "parameters": {
        "jsCode": "const html = $input.first().json.data;\nconst headers = $input.first().json.headers || {};\nconst cookies = headers['set-cookie'] || [];\n\nif (!html) {\n  throw new Error(\"HTML body is undefined. Check the previous node's output.\");\n}\nconst regex = /<script id=\"__UNIVERSAL_DATA_FOR_REHYDRATION__\" type=\"application\\/json\">([\\s\\S]*?)<\\/script>/;\nconst match = html.match(regex);\n\nif (match) {\n  const jsonStr = match[1];\n  const data = JSON.parse(jsonStr);\n  const videoUrl = data?.__DEFAULT_SCOPE__?.[\"webapp.video-detail\"]?.itemInfo?.itemStruct?.video?.playAddr;\n  if (!videoUrl) {\n    throw new Error(\"Could not find video URL in the JSON data.\");\n  }\n  return [{ json: { videoUrl, cookies: cookies.join('; ') } }];\n} else {\n  throw new Error(\"Could not find __UNIVERSAL_DATA_FOR_REHYDRATION__ script in the HTML.\");\n}"
      },
      "typeVersion": 2,
      "notes": "This code node performs automated tasks as part of the workflow."
    },
    {
      "id": "f574ccb8-6f5f-4e55-a2d5-7ad775d3c4e5",
      "name": "Output video file without watermark",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        900,
        20
      ],
      "parameters": {
        "url": "{{ $env.BASE_URL }}",
        "options": {
          "response": {
            "response": {
              "responseFormat": "file"

View on GitHub (pinned to 94007c1445)

Solutions

  1. Check the upstream HTTP Request node's execution output to see where the HTML actually landed (json.data vs json.body vs json.data.body).
  2. Set the HTTP node Response Format to 'Text/String' (or 'autodetect' with the body expected as a string) so the HTML arrives as json.data.
  3. Add a User-Agent header and verify the request returns 200 — a 403/captcha page will still be defined but fail later scraping, while a rejected request can yield undefined.
  4. Guard with a clearer message that dumps Object.keys($input.first().json) to diagnose shape drift.

Example fix

// before
const html = $input.first().json.data;
if (!html) {
  throw new Error("HTML body is undefined. Check the previous node's output.");
}

// after
const first = $input.first().json;
const html = first.data ?? first.body ?? first.data?.body;
if (typeof html !== 'string' || html.length === 0) {
  throw new Error(`HTML body is undefined. Available keys: ${Object.keys(first).join(', ')}`);
}
Defensive patterns

Strategy: type-guard

Validate before calling

const first = $input.first().json;
const html = first.data ?? first.body ?? first.data?.body;
const ok = typeof html === 'string' && html.length > 0;

Type guard

function hasHtmlBody(j) {
  const b = j?.data ?? j?.body ?? j?.data?.body;
  return typeof b === 'string' && b.length > 0;
}

Prevention

When it happens

Trigger: The upstream HTTP Request node returned an error response or was configured with responseFormat 'autodetect'/'json' so the raw body is not at json.data; the request was blocked (403/captcha) and returned an error object; the response property name differs (e.g. json.body, json.data.body for n8n's full-response option).

Common situations: HTTP node 'Response Format' set to JSON instead of Text/String; 'Include Response Headers and Status' toggled, nesting the body under data.body; TikTok blocking the request (bot detection, missing User-Agent) so the body is empty; workflow imported from another instance where the HTTP node version/options differ.

Related errors


AI-assisted analysis of Zie619/n8n-workflows@94007c1445 (2026-08-15). Data as JSON: /api/errors/6d35d96bf6358ba2. Report an issue: GitHub.