← CodeClarityLab Home
Browse by Category
+ added · updated 7d
← Back to glossary

FormData API

javascript ES2015 Intermediate
debt(d7/e1/b3/t9)
d7 Detectability Operational debt — how invisible misuse is to your safety net

Closest to 'only careful code review or runtime testing' (d7). The detection_hints note that automated detection is 'no' and ESLint is listed but cannot catch the semantic mistake of manually setting Content-Type or forgetting CSRF appends without a highly specific custom rule. The bug manifests as a broken upload at runtime — the request goes out but PHP receives nothing, which requires runtime testing or careful review to catch.

e1 Effort Remediation debt — work required to fix once spotted

Closest to 'one-line patch or single-call swap' (e1). The quick_fix is exactly one change: remove the manually-set Content-Type header (or add one FormData.append call for CSRF). No refactoring needed — it's a single-line deletion or addition at the call site.

b3 Burden Structural debt — long-term weight of choosing wrong

Closest to 'localised tax' (b3). The applies_to scope is web contexts only, and the pattern is confined to individual form-submission call sites. Each affected fetch/XHR call needs the correct pattern, but the rest of the codebase is unaffected. It doesn't impose a cross-cutting architectural burden.

t9 Trap Cognitive debt — how counter-intuitive correct behaviour is

Closest to 'catastrophic trap — the obvious way is always wrong' (t9). The misconception field explicitly states that the 'obvious' developer action — manually setting Content-Type: multipart/form-data — is exactly wrong and silently breaks the upload by omitting the browser-generated boundary parameter. This directly contradicts how Content-Type headers work everywhere else (where you set them explicitly), making it a classic t9 trap.

About DEBT scoring →

Also Known As

FormData multipart form data AJAX file upload

TL;DR

FormData constructs key-value pairs from HTML forms for AJAX submission to PHP backends — supports file uploads without page reload.

Explanation

FormData mirrors PHP's $_POST and $_FILES. new FormData(formElement) captures all fields automatically. Append extra data with .append(). Submit via fetch() with no Content-Type header — the browser sets multipart/form-data with the correct boundary automatically. PHP reads files via $_FILES and fields via $_POST as normal. Never set Content-Type: application/json when sending FormData — it breaks multipart encoding.

Common Misconception

You must set Content-Type: multipart/form-data manually when using FormData — setting it manually omits the boundary parameter and breaks the upload; let the browser set it automatically.

Why It Matters

FormData lets you submit PHP forms including file uploads entirely via JavaScript without page reload, keeping PHP's server-side validation and file handling unchanged.

Common Mistakes

  • Setting Content-Type header manually when using FormData
  • Not appending CSRF token to FormData before submit
  • Using JSON.stringify on FormData — it serialises to empty object

Code Examples

✗ Vulnerable
// Wrong — breaks multipart boundary:
fetch('/upload.php', {
    method: 'POST',
    headers: { 'Content-Type': 'multipart/form-data' }, // DO NOT SET
    body: new FormData(form)
});
✓ Fixed
const fd = new FormData(document.querySelector('#upload-form'));
fd.append('_token', document.querySelector('meta[name=csrf-token]').content);

// No Content-Type header — browser sets it correctly:
const res = await fetch('/upload.php', { method: 'POST', body: fd });
const data = await res.json();
// PHP reads normally: $_POST['field'], $_FILES['file']

Added 17 Mar 2026
Edited 22 Mar 2026
Views 32
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings F 0 pings S 0 pings S 1 ping M 0 pings T 0 pings W 0 pings T 0 pings F 0 pings S 1 ping S 0 pings M 1 ping T 0 pings W 0 pings T 0 pings F 0 pings S 1 ping S 3 pings M 0 pings T 1 ping W 0 pings T 0 pings F 0 pings S 1 ping S 0 pings M 0 pings T 0 pings W 0 pings T 1 ping F 0 pings S
No pings yet today
Amazonbot 9 Perplexity 7 Unknown AI 4 ChatGPT 3 Ahrefs 2 Majestic 1 Google 1
crawler 25 crawler_json 1 pre-tracking 1
DEV INTEL Tools & Severity
🟡 Medium ⚙ Fix effort: Low
⚡ Quick Fix
new FormData(formEl) + fetch with no Content-Type header — PHP receives $_POST and $_FILES as normal
📦 Applies To
javascript ES2015 web
🔗 Prerequisites
🔍 Detection Hints
fetch POST with FormData and manually set Content-Type header; not appending CSRF token to FormData
Auto-detectable: ✗ No eslint
⚠ Related Problems
🤖 AI Agent
Confidence: Medium False Positives: Medium ✗ Manual fix Fix: Medium Context: Function Tests: Update
CWE-352

✓ schema.org compliant