Converting cURL Commands to Code -- Python, JavaScript, and More

Learn how to translate cURL commands from API docs into working code in Python, JavaScript, Go, and other languages.

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)
  • -d or --data: Sends request body data
  • -u username:password: Adds basic authentication
  • -b "name=value": Sends cookies
  • -F: Sends form data (multipart/form-data)
  • -k or --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=False to 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.

Related Tools