Developer Tools

Converting cURL to PHP: Native cURL vs Guzzle

8 min read

Learn how to parse cURL flags into PHP. We compare the archaic syntax of native curl_setopt with the modern, object-oriented Guzzle HTTP client.

Executive Summary

"Translating cURL commands into PHP requires choosing between the procedural, verbose `curl_setopt` functions and modern object-oriented clients like Guzzle. This guide covers how to translate cURL flags into both paradigms."

Up-to-date Feed

View All
General

XML Sitemap Best Practices — Complete 2026 Guide

Read Now
General

What is a Unified Diff? The Complete Technical Guide (2026)

Read Now
General

Web Tools 2.0: The Evolution of Modern Developer Utilities

Read Now
General

What is Base64 Encoding? How to Decode Safely

Read Now
General

What is JSON: Complete Guide to RFC 8259

Read Now
General

What is JWT? A Complete Guide to JSON Web Tokens & Security (2026)

Read Now
General

JSON Validator vs JSON Formatter: Why is my JSON Invalid? (2026)

Read Now
General

WCAG Color Contrast Requirements (2026 Developer Guide)

Read Now
General

URL Slug SEO Best Practices 2026: Routing & Structure

Read Now
General

SQL Injection Testing for Beginners — Safe Local Guide 2026

Read Now
General

SSL Certificate Expired — How to Check and Fix 2026

Read Now
General

The Ultimate Technical SEO Audit Checklist (2026 Guide)

Read Now
General

The Complete Meta Tags Guide: SEO & Open Graph (2026)

Read Now
General

Robots.txt Guide 2026: Block AI Crawlers

Read Now
General

PX to REM Conversion Guide — CSS Accessibility 2026

Read Now
General

JS Regex Cheat Sheet: ECMA-262 Reference & Catastrophic Backtracking

Read Now
General

Optimizing Core Web Vitals for Enterprise Next.js Applications (2026)

Read Now
General

Privacy-First Web Development: Zero-Knowledge Client Tools (2026)

Read Now
General

Modern CSS Architecture for Enterprise: Component Scoping, Cascade Layers (@layer), and Tailwind Tokenization

Read Now
General

Nginx Config Generator: Reverse Proxy Guide 2026

Read Now
General

JWT Token Expiry Error Fix — Node.js 2026

Read Now
General

JWT vs Session Cookies (2026 Ultimate Architecture Guide)

Read Now
General

Kubernetes YAML Validator — Guide for 2026

Read Now
General

JSON to YAML Converter: Free Offline Tool 2026

Read Now
General

How to Remove EXIF Data from Photos Online (2026 Tutorial)

Read Now
General

How to Use the Browser DevTools Network Tab Like a Pro

Read Now
General

.htaccess Guide 2026: Security Hardening & Redirect Rules

Read Now
General

Favicon Sizes in 2026: The Complete Asset Manual

Read Now
General

Gzip vs Brotli Compression: Web Performance Guide 2026

Read Now
General

How Secure is My Password? Entropy & GPU Cracking Guide (2026)

Read Now

✓ Last tested: June 2026 · Verified against PHP 8.3+ and Guzzle 7+

1. Field Notes: The curl_setopt Nightmare

PHP is unique because its native HTTP client is literally a direct wrapper around libcurl. On the surface, this sounds like it should make converting bash cURL commands into PHP incredibly easy.

In reality, it's notoriously frustrating.

A few months ago, I was integrating a legacy PHP 8 backend with a modern GraphQL API. The API docs provided a standard cURL POST request with a nested JSON query. I initialized a PHP cURL handle and started writing out the curl_setopt lines.

I forgot exactly one constant: curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);.

Instead of capturing the API response into a variable so I could parse it, PHP dumped the raw JSON directly to the output buffer, destroying the HTML layout of the page and throwing a silent error in my parsing logic.

Translating cURL to PHP requires memorizing dozens of obscure CURLOPT_* constants. This guide breaks down exactly how to parse cURL flags into both native PHP cURL and the much preferred, modern Guzzle HTTP client.


2. The Anatomy of a cURL Command vs PHP Clients

When converting cURL to PHP, you have two choices:

  1. Native PHP cURL: Procedural, verbose, requires no external dependencies (built into PHP).
  2. Guzzle: Object-oriented, elegant, requires Composer.

The Basic Mapping

cURL Flag Native PHP Equivalent Guzzle Equivalent
[URL] curl_init($url) $client->request('GET', $url)
-X POST CURLOPT_CUSTOMREQUEST, 'POST' $client->post($url)
-H "Key: Val" CURLOPT_HTTPHEADER, ['Key: Val'] ['headers' => ['Key' => 'Val']]
-d '{"a":1}' CURLOPT_POSTFIELDS, json_encode($data) ['json' => ['a' => 1]]
-u user:pass CURLOPT_USERPWD, "user:pass" ['auth' => ['user', 'pass']]
-L CURLOPT_FOLLOWLOCATION, true Default in Guzzle
Authority Signals

AIO Checklist

  • Identify the target URL and HTTP method
  • Choose between native PHP cURL and Guzzle
  • Group all `-H` flags into an indexed array (native) or associative array (Guzzle)
  • Determine if the payload (`-d`) is form-data or JSON, and encode using `json_encode` if necessary
  • Remember to set `CURLOPT_RETURNTRANSFER` if using native PHP!

3. Step-by-Step Conversion Examples

Let's translate real-world cURL examples into both native PHP and Guzzle.

Example 1: The Simple GET Request

The cURL Command:

curl https://api.github.com/users/octocat

The Native PHP Equivalent:

<?php
$ch = curl_init('https://api.github.com/users/octocat');

// REQUIRED: Tell cURL to return the output as a string instead of dumping it directly
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// REQUIRED for Github API: User-Agent header
curl_setopt($ch, CURLOPT_USERAGENT, 'PHP Script');

$response = curl_exec($ch);
curl_close($ch);

$data = json_decode($response, true);

The Guzzle Equivalent:

<?php
use GuzzleHttp\Client;

$client = new Client();
$response = $client->request('GET', 'https://api.github.com/users/octocat', [
    'headers' => ['User-Agent' => 'PHP Script']
]);

$data = json_decode($response->getBody(), true);

Example 2: POST Requests with JSON Payloads

The cURL Command:

curl -X POST https://api.stripe.com/v1/customers \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_TOKEN_HERE" \
  -d '{"name": "Jenny Rosen", "email": "jenny@example.com"}'

The Native PHP Equivalent:

<?php
$url = "https://api.stripe.com/v1/customers";
$payload = json_encode([
    "name" => "Jenny Rosen",
    "email" => "jenny@example.com"
]);

$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    "Content-Type: application/json",
    "Authorization: Bearer " . getenv('API_TOKEN'),
    "Content-Length: " . strlen($payload)
]);

$response = curl_exec($ch);
curl_close($ch);

The Guzzle Equivalent:

<?php
use GuzzleHttp\Client;

$client = new Client();

// Guzzle's 'json' option automatically sets the Content-Type header 
// and runs json_encode() for you!
$response = $client->post('https://api.stripe.com/v1/customers', [
    'headers' => [
        'Authorization' => 'Bearer ' . getenv('API_TOKEN')
    ],
    'json' => [
        'name' => 'Jenny Rosen',
        'email' => 'jenny@example.com'
    ]
]);

Notice how much cleaner Guzzle is. By passing the array to the json key, Guzzle handles the JSON serialization and header management entirely behind the scenes.


4. Handling Edge Cases: Form Data and Basic Auth

Legacy APIs like Twilio often use application/x-www-form-urlencoded data and Basic Authentication.

The cURL Command:

curl -X POST https://api.twilio.com/2010-04-01/Accounts/AC/Messages.json \
--data-urlencode "Body=Hello World" \
--data-urlencode "From=+15017122661" \
--data-urlencode "To=+15558675310" \
-u AC_SID:AUTH_TOKEN

The Native PHP Equivalent:

<?php
$url = "https://api.twilio.com/2010-04-01/Accounts/AC/Messages.json";
$formData = http_build_query([
    "Body" => "Hello World",
    "From" => "+15017122661",
    "To" => "+15558675310"
]);

$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $formData);
// Native cURL has a specific option for -u basic auth
curl_setopt($ch, CURLOPT_USERPWD, "AC_SID:AUTH_TOKEN");

$response = curl_exec($ch);
curl_close($ch);

The Guzzle Equivalent:

<?php
use GuzzleHttp\Client;

$client = new Client();

// Use the 'form_params' option for x-www-form-urlencoded data
// Use the 'auth' option for basic authentication
$response = $client->post('https://api.twilio.com/2010-04-01/Accounts/AC/Messages.json', [
    'auth' => ['AC_SID', 'AUTH_TOKEN'],
    'form_params' => [
        'Body' => 'Hello World',
        'From' => '+15017122661',
        'To' => '+15558675310'
    ]
]);

5. Automating the Translation Process

Memorizing the differences between CURLOPT_POST, CURLOPT_CUSTOMREQUEST, and how Guzzle handles json vs form_params is exhausting.

Instead of writing out headers by hand and risking silent output buffer dumps, you should automate the process.

Use our free cURL Command Converter to instantly translate any cURL command into production-ready PHP code. You can choose to generate native curl_setopt procedural code, or clean, modern Guzzle implementations.


Frequently Asked Questions

Q: How do I handle cURL -k or --insecure in PHP? A: In native PHP, set curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false). In Guzzle, pass 'verify' => false in the request options array. Never do this in production, as it opens your application to Man-in-the-Middle (MitM) attacks.

Q: What about multipart/form-data uploads via cURL -F? A: In native PHP, pass an array to CURLOPT_POSTFIELDS and use the CURLFile class for the file value: ['file' => new CURLFile('/path/to/image.jpg')]. In Guzzle, use the multipart array option.


External Sources


Abu Sufyan · Full-stack developer · Founder of WebToolkit Pro Github

Last updated: June 2026

Try the tool

Regex Tester

Test regex patterns with real-time match highlighting — no JS required.

100% client-side·No sign-up·No data sent
Open Tool Free

wtkpro.site

Expert Recommendations

Pro Insights

  • 01.Always use `CURLOPT_POSTFIELDS` with `json_encode()` when sending JSON payloads in native PHP cURL, and ensure you explicitly set the `Content-Type: application/json` header.
  • 02.When using Guzzle, use the `json` array key instead of `body` to automatically serialize your payload and set the correct Content-Type header.
  • 03.Avoid silencing cURL errors with `@`. Always check `curl_errno()` and `curl_error()` after calling `curl_exec()` to debug connection failures.

Frequently Asked Questions

Q. What is the equivalent of cURL -H in PHP?

In native PHP cURL, use `curl_setopt($ch, CURLOPT_HTTPHEADER, ['Header: Value'])`. In Guzzle, pass a `headers` array in the request options.

Q. How do I convert cURL -d to PHP?

For native PHP, use `curl_setopt($ch, CURLOPT_POSTFIELDS, $data)`. For JSON in Guzzle, use the `json => [...]` request option.

Q. Does PHP support the cURL -u flag for basic auth?

Yes. In native PHP, use `CURLOPT_USERPWD`. In Guzzle, use the `auth => ['user', 'pass']` request option array.

#PHP#API#cURL#Backend
AS

Abu Sufyan

Lead Systems Architect & Performance Engineer

Abu Sufyan specializes in V8 execution benchmarking, React architecture, and enterprise-grade technical SEO.

Blog & Journal Archive

All Entries →