cURL to Node.js
Convert a cURL command into a Node.js fetch call.
Related Tools
Convert a cURL command into a Python requests call.
Convert a cURL command into a PHP curl_setopt call.
Beautify and pretty-print JSON with configurable indentation.
Validate JSON against a JSON Schema with JSON-pointer error paths.
Convert a cURL command into a Go net/http request.
Convert a cURL command into a Rust reqwest request.
Documentation
What is curl-to-Node?
This tool converts a curl command into a Node.js script that uses the built-in fetch API — the same fetch signature browsers use, available globally in Node 18+ without installing axios, node-fetch, or any other package.
How it works
The curl command is tokenized and parsed into method, url, headers, body, form fields, and auth. Each maps onto fetch's second argument: method, a headers object, and a body string taken verbatim from -d/--data — never re-parsed as JSON and re-serialized, so the exact bytes curl would send are preserved. -u user:pass is the one flag that needs a small computation rather than a straight mapping: fetch has no native "basic auth" option, so the generator emits Buffer.from('user:pass').toString('base64') at the top of the script and injects it into an Authorization header built from a template literal (Basic plus the credentials) — computed at runtime rather than baked in as a precomputed string, since Buffer is a Node global available wherever the script actually executes.
Features
- Zero-install output — uses global
fetch, nonpm installrequired - Body passed through as a raw string, not re-encoded
-uBasic Auth computed viaBuffer.from(...).toString('base64')at runtime-F/--form uploads become aFormDatainstance, with file fields stubbed for you to attach real bytes- Uses top-level
await, so it runs directly as an ES module without wrapping in an async function
Example
Input: curl -X POST https://api.example.com/v1/login -H "Content-Type: application/json" -u admin:s3cret -d '{"username":"admin","remember":true}'
Output:
const credentials = Buffer.from('admin:s3cret').toString('base64');
const response = await fetch('https://api.example.com/v1/login', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Basic ${credentials}`,
},
body: '{"username":"admin","remember":true}',
});
const data = await response.text();
console.log(response.status, data);Common errors
Top-level await only works in an ES module context — either a file with a .mjs extension, or a "type": "module" entry in package.json. In a plain CommonJS .js file you'll get a syntax error and need to wrap the code in an async function. Also, running the output on Node < 18 fails with "fetch is not defined" — either upgrade Node or install node-fetch and add the import.
Best practices
Check response.ok before trusting the body — unlike some other HTTP clients, fetch doesn't throw on 4xx/5xx status codes, only on network failures. Wrap the call in a try/catch for those network-level errors, and avoid logging the raw credentials variable anywhere in production logs.
Frequently Asked Questions
Does this need a package like axios or node-fetch?▾
No — fetch has been built into Node.js since v18 with no extra install, so the generated code works out of the box on any reasonably current Node version.
What Node version is required?▾
Node 18 or later, since that's when global fetch and FormData landed without a flag. If you're on an older Node version, install node-fetch or axios and adapt the call — the options object (method, headers, body) maps over directly.
How is Basic Auth handled?▾
The generated code computes the base64 credentials at runtime with Buffer.from(...).toString('base64'), rather than hardcoding a precomputed value — Buffer is a Node global, available wherever this generated code actually runs.
Does it support file uploads via -F?▾
Non-file fields are appended directly to a FormData instance. File fields include a TODO comment, since attaching real file bytes needs your filesystem (fs.readFileSync + Blob) which the generator can't access from your browser.