# From cURL command to code: fetch, PHP cURL, Python requests, Node

> Convert a cURL command into fetch JavaScript, PHP cURL, Python requests or Node code. Handles method, headers, JSON body, bearer token, basic auth, cookies and multipart form. Client-side.

Free in-browser tool (no upload): https://www.mauriziofonte.it/tools/curl-to-code-converter

Paste a **cURL** command (the one every API's docs show) and get the equivalent code in **fetch JavaScript**, **PHP cURL**, **Python requests** or **Node**. The tool reads method (`-X`), headers (`-H`), body (`-d`/`--data`/`--json`), basic auth (`-u`), cookies (`-b`) and multipart form (`-F`), and generates ready-to-paste code. Fully **client-side**: the command never leaves your browser.

## How to use the converter

1. **Copy the cURL command** - From an API's documentation (Stripe, GitHub, OpenAI, Twilio all show cURL examples), from a client like Postman or Insomnia ('Copy as cURL'), or from the browser DevTools (Network, right-click the request, 'Copy as cURL'). Paste it into the field, even across multiple lines with backslash continuations: the parser handles them.
2. **Pick the target language** - fetch for JavaScript in the browser or Node 18+, PHP cURL for a PHP backend, Python requests for scripts and automation, Node for a server-side HTTP client. Each target emits idiomatic code for that language, not a literal transliteration.
3. **Convert** - The parser tokenizes the command honouring shell quoting, reads method, headers, body, authentication, cookies and form, then generates the equivalent code. The method is inferred the way cURL does it: if there is a `-d` without `-X`, the method is POST.
4. **Copy and integrate** - Copy the code and paste it into your project. Always replace sensitive values (bearer tokens, passwords, API keys) with environment variables: a secret committed in cleartext into the repository must be considered compromised and rotated.

## Why convert a cURL command into code

**cURL is the lingua franca of APIs.** Open the docs of Stripe, GitHub, OpenAI, Twilio or any serious REST API: the request examples are almost always `curl` commands. It is the most concise, language-neutral way to describe an HTTP call: method, URL, headers, body. The friction appears when you have to go from that command-line example to the code that actually runs inside your application: a fetch in the frontend, a requests client in a Python script, a cURL call in a PHP backend. This tool does exactly that translation, keeping the HTTP semantics intact.

**What the parser reads.** The command is tokenized honouring shell quoting rules (single quotes, double quotes, backslash escapes), then each option is mapped to the corresponding HTTP concept:

- `-X, --request` sets the method (GET, POST, PUT, PATCH, DELETE). If it is missing but a body is present, the method becomes POST, exactly as cURL does.

- `-H, --header` adds a request header. It is repeatable: `-H "Authorization: Bearer ..." -H "Content-Type: application/json"`.

- `-d, --data / --data-raw / --data-binary` defines the body. Multiple `-d` are joined with `&`. With no explicit Content-Type, cURL uses `application/x-www-form-urlencoded`.

- `--json` (cURL 7.82+) is a shortcut for body plus `Content-Type: application/json` plus `Accept: application/json`.

- `-u, --user user:password` produces the `Authorization: Basic` header with the pair base64-encoded.

- `-b, --cookie` sets the `Cookie` header.

- `-F, --form` builds a `multipart/form-data` body: `-F "field=value"` for a field, `-F "file=@path"` for an upload.

- The query string is part of the URL and is preserved as-is.

**fetch, requests, PHP cURL, Node: four different philosophies.** The same command produces very different code depending on the target, and the differences matter.

`fetch` (JavaScript) is async and Promise-based, available natively in the browser and in Node from version 18. It does not serialize JSON for you: the body must be passed as a string via `JSON.stringify(...)`, and you set the `Content-Type` by hand in the headers. In the browser it is subject to the target server's CORS policy.

`requests` (Python) is synchronous and high-level. The `json=` parameter serializes the dictionary and sets `Content-Type: application/json` automatically; `data=` with a dictionary produces a form-urlencoded body; `files=` handles multipart; `auth=(user, password)` does basic auth. It is the most compact target.

PHP's `cURL` (the libcurl extension) is imperative and verbose: `curl_init()`, a sequence of `curl_setopt()` calls (`CURLOPT_CUSTOMREQUEST`, `CURLOPT_HTTPHEADER`, `CURLOPT_POSTFIELDS`, `CURLOPT_USERPWD`), then `curl_exec()`. In exchange for the verbosity it gives full control over TLS, timeouts and redirects.

The `Node` target uses the global `fetch` (Node 18+), the modern idiomatic approach for a server-side HTTP client, avoiding the low-level stream-and-callback `https` module.

**Headers, authentication and body: where sloppy converters get it wrong.** A bearer token is just an `Authorization: Bearer <token>` header, so it passes straight through as a header in every language. Basic auth instead has to be translated: cURL uses `-u user:pass`, but in code it becomes `btoa()` in JavaScript, `base64_encode()` in PHP, the `auth=` tuple in requests. A JSON body must be serialized with the language's proper function, not pasted as a raw string. Multipart is not a simple header: it needs `FormData` in JS, the `files=` argument in requests, an associative array with `CURLFile` in PHP.

**Privacy: everything in the browser.** The command you paste often contains tokens, API keys or passwords (the `-H "Authorization: ..."`, the `-u user:pass`). That is why the tool works entirely client-side: parsing and code generation happen in JavaScript in your browser, nothing is sent to a server. You can convert commands with real secrets without them leaving the machine, though the golden rule remains to replace them with environment variables in the final code.

## Glossary

- **cURL**: Client URL: a command-line tool (and library, libcurl) for making HTTP requests and dozens of other protocols. It is the de facto standard for showing API call examples in documentation.
- **fetch**: JavaScript API for HTTP requests, Promise-based, native in modern browsers and in Node.js from version 18. It replaces the old XMLHttpRequest with a cleaner, more composable interface.
- **requests**: Python's HTTP library, a byword for simplicity ('HTTP for Humans'). It abstracts headers, sessions, authentication, JSON serialization and multipart behind a synchronous, readable API.
- **HTTP header**: A name:value pair sent with an HTTP request or response to carry metadata: content type (Content-Type), authentication (Authorization), cookies, caching. In cURL they are added with `-H`.
- **Bearer token**: An authorization scheme where the client sends an opaque token or a JWT in the `Authorization: Bearer <token>` header. It is the OAuth 2.0 standard for modern REST APIs.
- **Basic auth**: HTTP basic authentication (RFC 7617): username and password joined with `:` and base64-encoded in the `Authorization: Basic` header. It is not encryption: use it only over HTTPS.
- **Payload**: The body of an HTTP request: the data sent to the server, typically JSON, form-urlencoded or multipart. In cURL it is defined with `-d`, `--data` or `--json`.
- **Multipart**: The `multipart/form-data` format for sending fields and files in a single request, used for uploads. Each part has its own headers and a boundary separates the parts. In cURL it is built with `-F`.

## Frequently asked questions about the cURL converter

### What does this tool do?

It takes a `curl` command (method, URL, headers, body, authentication, cookies, form) and generates the equivalent code in the language you pick: fetch JavaScript, PHP with the cURL extension, Python with the requests library, or Node with fetch. It turns the cURL examples in API documentation into ready-to-integrate code, without hand-translating headers and options.

### Does the data stay in the browser?

Yes, 100%. Parsing the command and generating the code happen entirely in JavaScript in your browser: nothing is sent to a server, there is no network call. So you can convert commands that contain real secrets (bearer tokens, passwords in `-u`, API keys in headers) without them leaving your machine. It is still good practice to replace secrets with environment variables in the final code.

### Which languages does it support?

Four targets: `fetch` for JavaScript (browser and Node), `fetch` for server-side Node.js, PHP's `cURL` (libcurl with `curl_setopt`), and `requests` for Python. These are the most widely used HTTP libraries in their respective ecosystems. If you need a different target (Go, Ruby, Java, C#) the abstract HTTP request is the same: only the client's syntax changes.

### Does it handle authentication?

Yes, both common schemes. A **bearer token** passed with `-H "Authorization: Bearer ..."` stays a header and is carried over verbatim in every language. **Basic auth** passed with `-u user:password` is translated idiomatically: `btoa('user:pass')` in fetch, `base64_encode()` or `CURLOPT_USERPWD` in PHP, the `auth=(user, password)` tuple in requests. Basic auth always goes over HTTPS because it is only base64, not encryption.

### Does it handle POSTing JSON?

Yes, it is the most common case. A `-d '{...}'` with `-H "Content-Type: application/json"`, or the `--json '{...}'` shortcut, is translated using the language's proper serialization: `JSON.stringify()` in fetch, the `json=` parameter in requests (which also sets the header), `json_encode()` with `CURLOPT_POSTFIELDS` in PHP. The body is never pasted as a raw string where the language expects an object.

### Does it convert multipart forms too?

Yes. The `-F` options become `FormData` in JavaScript, the `files=` or `data=` argument in requests, an associative array (with `CURLFile` for uploads) in PHP. Watch out for file references like `-F "file=@/path"`: in the generated code they become a reference to a file you must wire up yourself (a file input in the browser, a real path on the server), because the file content is not in the cURL command.

### Can I convert from code to cURL (the other way)?

Not in this version: the tool goes one way only, from cURL to code. For the reverse path, the fastest route is that browsers (DevTools, right-click the request, 'Copy as cURL') and API clients like Postman and Insomnia already offer a 'Copy as cURL' that rebuilds the command from the request. A code-to-cURL converter is a natural extension and is on the roadmap.

### Does it handle cookies?

Yes. A `-b, --cookie "name=value"` is translated into the corresponding `Cookie` header. Note however that real session handling (a login that sets a cookie, later requests that reuse it) needs a cookie jar: `requests.Session()` in Python, the `credentials: 'include'` option in fetch, `CURLOPT_COOKIEJAR`/`CURLOPT_COOKIEFILE` in PHP. A single Cookie header covers the static case, not the session lifecycle.

---
Tool by Maurizio Fonte, senior backend engineer. All tools: https://www.mauriziofonte.it/tools/
