API documentation often provides cURL examples. While cURL is excellent for quick testing in the terminal, you'll need to translate these commands into your application code. Converting cURL to Python, JavaScript, Go, or PHP isn't difficult once you understand how cURL flags map to language-specific HTTP libraries.
This guide walks you through the anatomy of a cURL command, explains what each flag does, and shows you how to convert that command into working code across multiple languages.
Understanding cURL Flags and Parameters
Before converting, you need to recognize what each part of a cURL command does:
-X METHOD: Specifies the HTTP method (GET, POST, PUT, DELETE, PATCH)-H "Header: value": Adds request headers (can be used multiple times)-dor--data: Sends request body data-u username:password: Adds basic authentication-b "name=value": Sends cookies-F: Sends form data (multipart/form-data)-kor--insecure: Ignores SSL certificate verification-i: Includes response headers in output-I: Shows only response headers (HEAD request)-v: Verbose output showing request and response details
Example cURL Commands
Let's start with a simple GET request:
curl https://api.example.com/users
This is straightforward -- just fetch a URL with default GET method.
A POST request with JSON data looks like:
curl -X POST https://api.example.com/users \
-H "Content-Type: application/json" \
-d '{"name":"Alice","email":"[email protected]"}'
With authentication:
curl -X POST https://api.example.com/users \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_TOKEN" \
-d '{"name":"Alice","email":"[email protected]"}'
Converting to Python (requests library)
Python's requests library is arguably the most popular HTTP library for converting cURL commands. The mapping is direct and readable:
import requests
# Simple GET request
response = requests.get('https://api.example.com/users')
print(response.json())
# POST with JSON data
response = requests.post(
'https://api.example.com/users',
headers={'Content-Type': 'application/json'},
json={'name': 'Alice', 'email': '[email protected]'}
)
print(response.status_code)
# POST with Bearer token authentication
response = requests.post(
'https://api.example.com/users',
headers={
'Content-Type': 'application/json',
'Authorization': 'Bearer YOUR_TOKEN'
},
json={'name': 'Alice', 'email': '[email protected]'}
)
# Basic authentication (using -u in curl)
response = requests.get(
'https://api.example.com/users',
auth=('username', 'password')
)
# Multiple headers
response = requests.post(
'https://api.example.com/users',
headers={
'Content-Type': 'application/json',
'Authorization': 'Bearer TOKEN',
'X-Custom-Header': 'value'
},
json={'name': 'Alice'}
)
# Ignore SSL verification (like -k flag)
response = requests.get(
'https://api.example.com/users',
verify=False # Not recommended for production
)
Key points for Python:
- Use
json=parameter instead of manually setting headers and string conversion - Pass dictionaries to
headers=parameter - Use
auth=tuple for basic authentication - Set
verify=Falseto skip SSL validation (avoid in production)
Converting to JavaScript (fetch API)
Modern JavaScript uses the fetch API, which requires a bit more manual setup compared to Python's requests:
// Simple GET request
fetch('https://api.example.com/users')
.then(response => response.json())
.then(data => console.log(data));
// POST with JSON data
fetch('https://api.example.com/users', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: 'Alice',
email: '[email protected]'
})
})
.then(response => response.json())
.then(data => console.log(data));
// With Bearer token
fetch('https://api.example.com/users', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer YOUR_TOKEN'
},
body: JSON.stringify({
name: 'Alice',
email: '[email protected]'
})
})
.then(response => response.json())
.then(data => console.log(data));
// With basic authentication (encode credentials in header)
const credentials = btoa('username:password');
fetch('https://api.example.com/users', {
method: 'GET',
headers: {
'Authorization': 'Basic ' + credentials
}
})
.then(response => response.json())
.then(data => console.log(data));
// Modern async/await syntax
async function getUsers() {
const response = await fetch('https://api.example.com/users');
const data = await response.json();
return data;
}
Key points for JavaScript:
- Use
method:property (uppercase like POST, PUT, DELETE) - Always stringify JSON with
JSON.stringify() - For basic auth, manually encode with
btoa()and set Authorization header - The async/await syntax is cleaner than promise chains
Converting to Go
Go's net/http package requires more explicit setup but is still straightforward:
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
)
// Simple GET request
func getUsers() {
resp, err := http.Get("https://api.example.com/users")
if err != nil {
fmt.Println(err)
return
}
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
fmt.Println(string(body))
}
// POST with JSON
func createUser() {
data := map[string]string{
"name": "Alice",
"email": "[email protected]",
}
jsonData, _ := json.Marshal(data)
resp, err := http.Post(
"https://api.example.com/users",
"application/json",
bytes.NewBuffer(jsonData),
)
if err != nil {
fmt.Println(err)
return
}
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
fmt.Println(string(body))
}
// With custom headers and authentication
func createUserWithAuth() {
data := map[string]string{
"name": "Alice",
"email": "[email protected]",
}
jsonData, _ := json.Marshal(data)
req, _ := http.NewRequest(
"POST",
"https://api.example.com/users",
bytes.NewBuffer(jsonData),
)
req.Header.Add("Content-Type", "application/json")
req.Header.Add("Authorization", "Bearer YOUR_TOKEN")
// Basic authentication
req.SetBasicAuth("username", "password")
client := &http.Client{}
resp, _ := client.Do(req)
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
fmt.Println(string(body))
}
Key points for Go:
- Build requests with
http.NewRequest()for anything beyond simple GET/POST - Use
SetBasicAuth()method for authentication - Always defer
resp.Body.Close()to prevent leaks - Go requires explicit error handling
Handling Special Cases
Multipart Form Data
When converting a cURL command with -F flags for file uploads:
curl -X POST https://api.example.com/upload \
-F "file=@/path/to/file.txt" \
-F "description=My file"
Python version:
files = {
'file': open('/path/to/file.txt', 'rb'),
'description': (None, 'My file')
}
response = requests.post('https://api.example.com/upload', files=files)
JavaScript version requires FormData:
const formData = new FormData();
formData.append('file', fileInput.files[0]);
formData.append('description', 'My file');
fetch('https://api.example.com/upload', {
method: 'POST',
body: formData
})
.then(response => response.json());
Query Parameters
When your cURL command includes query strings, you can either append to the URL or use the library's parameter handling:
Python:
response = requests.get(
'https://api.example.com/users',
params={'page': 2, 'limit': 10}
)
JavaScript:
const url = new URL('https://api.example.com/users');
url.searchParams.append('page', '2');
url.searchParams.append('limit', '10');
fetch(url)
.then(response => response.json());
Common Gotchas
JSON vs. form data: Check the Content-Type header. If it's application/json, use JSON encoding. If it's application/x-www-form-urlencoded, send key=value pairs.
SSL certificate issues: The -k flag skips verification. Never use verify=False in production Python code or disable SSL in JavaScript. Fix certificate issues properly instead.
Status codes: Remember that a successful HTTP request (status 200-299) is different from a successful API response. Always check both the status code and response body.
Token expiration: Bearer tokens expire. Implement refresh logic in production applications instead of hardcoding tokens.
Rate limiting: APIs often rate limit requests. Add retry logic and respect Retry-After headers.
Tools to Help
Converting cURL manually works fine for simple requests, but for complex commands with many headers and nested JSON, consider using an online cURL converter tool. These tools handle the parsing and flag interpretation automatically, letting you focus on integrating the code into your application.
Whether you're building a Python backend, JavaScript frontend, or Go service, understanding how to convert from cURL gives you flexibility to work with any API. The key is recognizing which cURL flags correspond to which parts of your HTTP library's API, and you'll be translating quickly.