How to perform web requests with PHP using the cURL extension

The open source libcurl is client-side URL transfer library which supports a lot of protocols like FTP, HTTP, HTTPS  and works on a multitude of platforms. The PHP cURL module let us access the functionalities provided by the library from the PHP programming language. In this tutorial we will see how to install the module and how to use it to perform simple requests.

In this tutorial you will learn:

  • How to install the cURL module
  • The basic steps to follow to initialiaze a cURL session and perform a request
  • How to perform a GET request with PHP cURL
  • How to perform a POST request with PHP cURL

Software Requirements and Conventions Used

Software Requirements and Linux Command Line Conventions
Category Requirements, Conventions or Software Version Used
System Os-independent
Software The php-curl package
Other Basic knowdlege of PHP and HTTP
Conventions # – requires given linux commands to be executed with root privileges either directly as a root user or by use of sudo command
$ – requires given linux commands to be executed as a regular non-privileged user

Before we begin

Before we proceed further in this tutorial we must check that the cURL extension is installed in our system. It is almost certainty the case, however the command to install it on Fedora is:

$ sudo dnf install php-curl

To install the extension on Debian and derivatives we can instead run:

$ sudo apt-get install php-curl

On Archlinux the extension is merged into the main PHP package, so to install it we can run:

$ sudo pacman -S php

Once we are sure cURL support is enabled, we can proceed and see how to create and customize a session and perform a request.

Main steps

The steps we need to perform an HTTP request when working with cURL are basically 4:

  1. Create a session;
  2. Customize the session by using available constants;
  3. Execute the session;
  4. Close the session;

To each one of the steps mentioned above corresponds a dedicated function, respectively:

  1. curl_init;
  2. curl_setopt;
  3. curl_exec;
  4. curl_close;

Let’s proceed in order.

Initializing a new cURL session: curl_init

To initialize a new cURL session we use the curl_init function. This function takes an optional argument which is the URL to be used for the request we want to perform. The argument is optional because we can alternatively pass it by specifying it as the value of the CURLOPT_URL option, using curl_setopt. The function returns an handler we need to pass in the other functions as the first argument. In the example below we used the NASA open API for the “astronomic picture of the day”, sending our request to its endpoint URL:

$handler = curl_init("");

Setting session options: curl_setopt

As we already said, to modify the behavior of cURL we can operate on the value of some options, referencing them by the use of some constants via the curl_setopt function. This function takes three arguments:

  1. The handler returned by the curl_init function;
  2. The cURL constant related to the option to modify;
  3. The value to set for the option;

The function returns TRUE on success and FALSE on failure. The list of the constants we can use with this function is too long to be exhaustively mentioned here, however, we already learned that we can use it to set the request URL:

curl_setopt($handler, CURLOPT_URL, "");  

Another often used constant is CURLOPT_RETURNTRANSFER. The value provided for the option must be a boolean: if set to true, when using the curl_exec function to execute a request, the response will be returned instead of displayed directly. Here is how we can set it:

curl_setopt($handler, CURLOPT_RETURNTRANSFER, true);

In case we need to set multiple options, instead of repeatedly call curl_setopt, we can represent the options we want to change and their values as key – value pairs into an array, and use the curl_setopt_array function to pass them at once:

$options = [
    CURLOPT_URL => "",

curl_setopt_array($handler, $options);

The curl_setopt_array function returns TRUE if all the settings are applied correctly, and FALSE as soon as an option could not be set.

Executing a session: curl_exec

Once we define the parameters and the options for our request, we can execute it: to perform such operation we use the curl_exec function. The function takes the handler returned by curl_init as its sole argument. By default it returns TRUE on success and FALSE on failure, however if the CURLOPT_RETURNTRANSFER option is set to true, just like we saw above, it does return the actual result of the request on success, and FALSE on failure. When executing our request without CURLOPT_RETURNTRANSFER, we obtain the following result:

$handler = curl_init("");
{"copyright":"Alistair Symon","date":"2019-07-25","explanation":"In brush
strokes of interstellar dust and glowing hydrogen gas, this beautiful skyscape
is painted across the plane of our Milky Way Galaxy near the northern end of the
Great Rift and the constellation Cygnus the Swan. Composed with three different
telescopes and about 90 hours of image data the widefield mosaic spans an
impressive 24 degrees across the sky. Alpha star of Cygnus, bright, hot,
supergiant Deneb lies near top center. Crowded with stars and luminous gas
clouds Cygnus is also home to the dark, obscuring Northern Coal Sack Nebula,
extending from Deneb toward the center of the view. The reddish glow of star
forming regions NGC 7000, the North America Nebula and IC 5070, the Pelican
Nebula, are just left of Deneb. The Veil Nebula is a standout below and left of
center. A supernova remnant, the Veil is some 1,400 light years away, but many
other nebulae and star clusters are identifiable throughout the cosmic scene. Of
course, Deneb itself is also known to northern hemisphere skygazers for its
place in two asterisms -- marking the top of the Northern Cross and a vertex of
the Summer

As you can see, the result of the request (information about the astronomic picture of the day) is directly printed in the terminal. If we use the aforementioned option, the result is returned by the function, and we can, for example, use it as the value of a variable:

curl_setopt($handler, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($handler);

An important thing to notice is that responses with an HTTP status code denoting an error, like for example 404, are not considered as a failure by the function, that will return TRUE on such cases. For example, here is what happens if we send a request to “”:

curl_setopt($handler, CURLOPT_URL, "");

Closing a session: curl_close

Once we finish working with our session, we must remember to close it, using the curl_close function. The function takes the handler returned by curl_init as its only argument and returns no values:


A POST request example

The request we sent above was a simple GET request. How can we send a POST request instead? The process requires some additional steps, but nothing to worry about. First we can define the data to include in the request as an associative array:

$post_data = ["fist_name" => "Luke", "last_name" => "skywalker"];

We can then proceed to create a session and set the needed options:

$handler = curl_init("");
$options = [CURLOPT_POST => true, CURLOPT_POSTFIELDS => $post_data];

We used two new options, CURLOPT_POST and CURLOPT_POSTFIELDS. The former, set to true, is needed in order for cURL to perform a POST request; the latter, instead, is used to set the actual data to pass in the request. As request endpoint we used the URL, which is provided by the httpbin service, and is dedicated to test POST requests. Let’s pass the options and execute our request:

curl_setopt_array($handler, $options);

The response returned by the service, is the description of the request we sent, here it is:

  "args": {},
  "data": "",
  "files": {},
  "form": {
    "fist_name": "Luke",
    "last_name": "skywalker"
  "headers": {
    "Accept": "*/*",
    "Content-Length": "255",
    "Content-Type": "multipart/form-data; boundary=------------------------0807f66ddf7311da",
    "Host": ""
  "json": null,
  "origin": ",",
  "url": ""

As you can notice, since we used an array to provide the request data ($post_data) the Content-Type header of our request was automatically set to multipart/form-data. With the same technique, we can also send json-encoded data: all we need to do is to encode the data as json and change the Content-Type and Content-Length headers. Here is the code:

$post_data = json_encode(["first_name" => "Luke", "last_name" => "Skywalker"]);
$options = [
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => $post_data,
        'Content-Type: application/json',
        'Content-Length: ' . strlen($post_data)
$handler = curl_init("");
curl_setopt_array($handler, $options);

This time, the content of the response is:

  "args": {},
  "data": "{\"first_name\":\"Luke\",\"last_name\":\"Skywalker\"}",
  "files": {},
  "form": {},
  "headers": {
    "Accept": "*/*",
    "Content-Length": "39",
    "Content-Type": "application/json",
    "Host": ""
  "json": {
    "last_name": "Skywalker",
    "name": "Luke"
  "origin": ",",
  "url": ""

We can now close our session:



In this tutorial we learn how to use the PHP cURL extension. We saw how to install the extensions in the most commonly used distributions, and the basic steps to perform GET and POST requests, using the curl_init, curl_setopt, curl_exec and curl_close functions, respectively used to initialize a session, set the available options, execute the session and close it. You may also be interested in our series of articles about performing HTTP requests with python.

Comments and Discussions
Linux Forum