Convert Curl to PHP

PHP's cURL extension is a wrapper around the same library the command-line tool uses, so every flag has a matching option. The names are longer, and two defaults are different enough to cause most first-attempt bugs.

Last updated . How this page is checked.

The command

curl -X POST https://httpbin.org/post \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name":"Ada","role":"admin"}'

Curl flag to PHP option

curlPHP cURL
URLCURLOPT_URL
-X METHODCURLOPT_CUSTOMREQUEST => 'METHOD'
-H "K: v"CURLOPT_HTTPHEADER => ['K: v']
-d stringCURLOPT_POSTFIELDS => $string
-F field=valueCURLOPT_POSTFIELDS => $array (an array means multipart)
-F "file=@x.png"new CURLFile('x.png') inside that array
-u user:pwCURLOPT_USERPWD => 'user:pw'
-LCURLOPT_FOLLOWLOCATION => true
-m 20CURLOPT_TIMEOUT => 20
--connect-timeout 5CURLOPT_CONNECTTIMEOUT => 5
-A stringCURLOPT_USERAGENT
-x proxyCURLOPT_PROXY
-kCURLOPT_SSL_VERIFYPEER => false

The same request in PHP

Build a handle, set options, execute. Use single-quoted PHP strings for anything containing a dollar sign, since double-quoted strings interpolate variables and would mangle a literal $ in a body or token. Encode JSON with json_encode rather than writing it by hand.

<?php
$ch = curl_init('https://httpbin.org/post');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST           => true,
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer ' . getenv('TOKEN'),
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS     => json_encode(['name' => 'Ada', 'role' => 'admin']),
    CURLOPT_TIMEOUT        => 20,
]);

$body = curl_exec($ch);
if ($body === false) {
    throw new RuntimeException('curl error: ' . curl_error($ch));
}
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
$data = json_decode($body, true);

Two defaults that bite

CURLOPT_RETURNTRANSFER. Without it, curl_exec prints the response straight into your page output and returns true. Set it and you get the body back as a string. Forgetting it is the single most common PHP cURL mistake.

CURLOPT_POSTFIELDS changes meaning with its type. A string is sent as given, with a form-encoded content type, like -d. An array is sent as multipart/form-data, like -F. Passing an array to an endpoint that expects URL-encoded fields fails in ways that look like missing parameters; wrap the array in http_build_query() to get the -d behaviour.

curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query(['a' => 1, 'b' => 2]));  // like -d
curl_setopt($ch, CURLOPT_POSTFIELDS, ['a' => 1, 'file' => new CURLFile('x.png')]); // like -F

Errors come in two layers

curl_exec returns false only for transport failures: DNS, connection, TLS, timeout. An HTTP 404 or 500 is a successful transfer as far as cURL is concerned, the same as the command line without -f. Check curl_error for the first kind and the response code for the second.

Common mistakes

  • Do not disable CURLOPT_SSL_VERIFYPEER to silence a certificate error. Point CURLOPT_CAINFO at a current CA bundle instead.
  • Redirects are not followed by default, matching the command line, and unlike most other HTTP libraries.
  • curl_close() has done nothing since PHP 8.0; the handle is freed when it goes out of scope.

Related curl examples

More under Converting curl

References

  • PHP manual: cURL — The curl_setopt options that correspond to command-line flags.
  • curl man page — What each flag being translated actually does.

These links leave api-tester.com, which is independent of the projects they point to.

FAQ

How do I convert a curl command to PHP?

Create a handle with curl_init, then set one CURLOPT option per flag: CURLOPT_HTTPHEADER for -H, CURLOPT_POSTFIELDS for -d, CURLOPT_CUSTOMREQUEST for -X, and CURLOPT_RETURNTRANSFER to get the response as a string.

Why does PHP curl_exec print the response instead of returning it?

Because CURLOPT_RETURNTRANSFER is not set. Set it to true and curl_exec returns the response body as a string.

How do I send JSON with PHP cURL?

Set CURLOPT_POSTFIELDS to json_encode($data) and add Content-Type: application/json to CURLOPT_HTTPHEADER.