Why Convert cURL Commands?
API documentation almost always shows request examples as cURL commands because cURL is universal, concise, and works from any terminal. But when you are writing production code, you need idiomatic HTTP client code in your language — not a cURL shell invocation.
Translating cURL flags manually is tedious and error-prone, especially with complex requests involving multiple headers, auth tokens, and JSON bodies. This guide explains the full cURL → language mapping.
Complete cURL Flag Reference
| cURL flag | Meaning | Example |
|---|---|---|
-X POST | HTTP method | -X GET, -X PATCH, -X DELETE |
-H "Key: Val" | Request header | -H "Authorization: Bearer token" |
-d '{...}' | Request body (string) | -d '{"name":"Ravi"}' |
--data-raw | Body (no extra encoding) | Same as -d for JSON |
-u user:pass | HTTP Basic Auth | Encodes to Base64 Authorization header |
-k | Skip TLS certificate verification | Dangerous — dev use only |
--compressed | Accept gzip response | Sets Accept-Encoding: gzip |
-L | Follow redirects | Most HTTP clients do this by default |
-v | Verbose output | For debugging — remove in code |
-s | Silent (no progress) | No equivalent needed in code |
--max-time N | Request timeout in seconds | Set via client/context configuration |
-o file | Save response to file | Write response body to file |
--cookie "k=v" | Send cookie | Set Cookie header |
--form "key=@file" | Multipart form upload | Multipart form data |
Full Example cURL Command
curl -X POST https://api.example.com/orders \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiJ9..." \
-H "X-Request-ID: req_abc123" \
--max-time 30 \
-d '{"productId": "prod_xyz", "quantity": 2, "coupon": "SAVE20"}'Go — net/http (Production-Ready)
package main
import (
"bytes"
"context"
"encoding/json"
"fmt"
"io"
"net/http"
"time"
)
type OrderRequest struct {
ProductID string `json:"productId"`
Quantity int `json:"quantity"`
Coupon string `json:"coupon,omitempty"`
}
type OrderResponse struct {
OrderID string `json:"orderId"`
Total float64 `json:"total"`
}
func createOrder(ctx context.Context, token string, req OrderRequest) (*OrderResponse, error) {
body, err := json.Marshal(req)
if err != nil {
return nil, err
}
// Create request with context for timeout/cancellation
httpReq, err := http.NewRequestWithContext(
ctx,
http.MethodPost,
"https://api.example.com/orders",
bytes.NewReader(body),
)
if err != nil {
return nil, err
}
httpReq.Header.Set("Content-Type", "application/json")
httpReq.Header.Set("Accept", "application/json")
httpReq.Header.Set("Authorization", "Bearer "+token)
httpReq.Header.Set("X-Request-ID", "req_abc123")
// Use a client with timeout (never use http.DefaultClient in production)
client := &http.Client{Timeout: 30 * time.Second}
resp, err := client.Do(httpReq)
if err != nil {
return nil, err
}
defer resp.Body.Close()
respBody, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
if resp.StatusCode != http.StatusCreated && resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("API error %d: %s", resp.StatusCode, string(respBody))
}
var result OrderResponse
if err := json.Unmarshal(respBody, &result); err != nil {
return nil, err
}
return &result, nil
}
// Usage:
// ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
// defer cancel()
// order, err := createOrder(ctx, token, OrderRequest{ProductID: "prod_xyz", Quantity: 2})Python — requests Library
import requests
from typing import Optional
def create_order(token: str, product_id: str, quantity: int,
coupon: Optional[str] = None) -> dict:
payload = {
"productId": product_id,
"quantity": quantity,
}
if coupon:
payload["coupon"] = coupon
response = requests.post(
"https://api.example.com/orders",
headers={
"Authorization": f"Bearer {token}",
"Accept": "application/json",
"X-Request-ID": "req_abc123",
},
json=payload, # auto-serializes and sets Content-Type: application/json
timeout=30, # seconds — corresponds to curl --max-time 30
)
response.raise_for_status() # raises HTTPError for 4xx/5xx
return response.json()Using json=payload instead of data=json.dumps(payload) automatically sets Content-Type: application/json and handles serialization.
JavaScript — fetch API
async function createOrder(token, { productId, quantity, coupon }) {
const controller = new AbortController();
const timeout = setTimeout(() => controller.abort(), 30_000); // 30s timeout
try {
const response = await fetch("https://api.example.com/orders", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Accept": "application/json",
"Authorization": `Bearer ${token}`,
"X-Request-ID": "req_abc123",
},
body: JSON.stringify({ productId, quantity, ...(coupon && { coupon }) }),
signal: controller.signal,
});
if (!response.ok) {
const err = await response.json().catch(() => ({}));
throw new Error(err.message || `HTTP ${response.status}`);
}
return await response.json();
} finally {
clearTimeout(timeout);
}
}cURL Auth Flags → Code
HTTP Basic Auth (`-u user:pass`):
// Go
req.SetBasicAuth("username", "password")
// → Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=# Python
requests.get(url, auth=("username", "password"))// JavaScript
headers: { "Authorization": "Basic " + btoa("username:password") }Bearer Token (`-H "Authorization: Bearer TOKEN"`):
headers: { "Authorization": `Bearer ${token}` }API Key in header (`-H "X-API-Key: your-key"`):
headers: { "X-API-Key": apiKey }Multipart File Upload (`--form "file=@path"`)
const form = new FormData();
form.append("file", fileBuffer, "upload.json");
form.append("description", "My file");
const response = await fetch("/api/upload", {
method: "POST",
headers: { "Authorization": `Bearer ${token}` },
// Do NOT set Content-Type manually — fetch sets it with boundary automatically
body: form,
});Production Code Checklist
| cURL behavior | Production code equivalent |
|---|---|
No timeout (-v output hangs) | Always set a timeout (30s recommended) |
| No error handling | Check status code and throw on 4xx/5xx |
-k skip TLS | Never in production — fix the certificate |
| No retry | Add exponential backoff for 429/503 |
| No tracing | Add correlation/request IDs in headers |
| Sync CLI | Use async/concurrent patterns in code |
Use JSONKit's cURL to Code tool to instantly convert any cURL command to production-ready code in Go, Python, JavaScript, PHP, and more — paste the command and copy the output.