Как задать Content-Type в запросах cURL на PHP

Раздел: Веб-разработка -> HTTP заголовки в PHP

Основные методы установки Content-Type в cURL

Наиболее эффективный и универсальный способ задать заголовок Content-Type в cURL - использовать опцию CURLOPT_HTTPHEADER с массивом строк, содержащих заголовки. Этот метод подходит для любых типов запросов (GET, POST, PUT, PATCH) и любых форматов данных (JSON, XML, форма, произвольный текст).


$ch = curl_init('https://example.com/api');
curl_setopt($ch, CURLOPT_POST, 1);
$data = ['key' => 'value'];
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    'Content-Type: application/json',
    'Accept: application/json'
]);
$response = curl_exec($ch);
curl_close($ch);
  

Php curl content type (установка content-type в curl в php)

В этом примере явно указывается Content-Type: application/json, что гарантирует правильную интерпретацию данных сервером. Такой подход исключает автоматическое определение типа контента, которое может быть неверным (например, для JSON строки cURL может установить application/x-www-form-urlencoded).

Типичная ошибка: если не указать Content-Type, а передать строку JSON через CURLOPT_POSTFIELDS, cURL по умолчанию выставит application/x-www-form-urlencoded. Это приводит к тому, что сервер не распознает данные как JSON. Решение - всегда явно задавать заголовок через CURLOPT_HTTPHEADER.

Как Content-Type устанавливается автоматически при передаче данных через CURLOPT_POSTFIELDS?

Если в CURLOPT_POSTFIELDS передать строку (например, результат http_build_query()), cURL автоматически установит заголовок Content-Type: application/x-www-form-urlencoded. При передаче массива с элементами типа CURLFile заголовок станет multipart/form-data с автоматической границей. Это удобно для стандартных HTML-форм.


$ch = curl_init('https://example.com/form');
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query(['name' => 'John', 'age' => 30]));
$response = curl_exec($ch);
  

Content type utf 8 php (кодировка utf-8 в content-type в php)

В данном случае ручная установка Content-Type не требуется. Однако при использовании нестандартных типов (JSON, XML) автоматический выбор не сработает.

Проблема: если передавать массив (не строку) без файлов, cURL может преобразовать его в строку вида key=value с Content-Type application/x-www-form-urlencoded. Если нужно отправить JSON, но случайно передать массив, данные будут закодированы как форма. Решение: всегда передавать строку JSON явно и указывать заголовок.

Цель использования: когда требуется отправить данные точно в том виде, как их понимает стандартная HTML-форма (например, для логина или поиска).

Как отправить JSON запрос с правильным Content-Type и авторизацией?

Используется CURLOPT_HTTPHEADER для указания Content-Type: application/json и, при необходимости, других заголовков (например, Authorization). Важно кодировать тело запроса через json_encode().


$url = 'https://api.example.com/data';
$headers = [
    'Content-Type: application/json',
    'Authorization: Bearer ' . $token
];
$data = ['user' => ['name' => 'Alice', 'role' => 'admin']];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
  

Php content type html (content-type: text/html в php)

Ошибка: если в массиве $headers случайно указать два заголовка Content-Type (например, один из них добавляется автоматически), сервер может получить неверный тип. cURL не удаляет дубликаты, они отправляются как есть. Решение: перед установкой убедиться, что в массиве нет одноимённых заголовков.

Случай использования: работа с REST API, где почти всегда требуется указывать Content-Type: application/json.

Как отправить XML данные с Content-Type application/xml?

Аналогично JSON, только тело запроса формируется как XML-строка, а Content-Type устанавливается на application/xml или text/xml.


$xmlString = '<?xml version="1.0"?>value';
$ch = curl_init('https://example.com/xml-endpoint');
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $xmlString);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    'Content-Type: application/xml'
]);
$response = curl_exec($ch);
  

Php content type text (content-type: text/plain в php)

Проблема: если XML содержит символы, недопустимые в кодировке по умолчанию (например, UTF-8 не подходит для содержимого), сервер может отвергнуть запрос. Решение: задать явно кодировку в объявлении XML и в заголовке, например Content-Type: application/xml; charset=utf-8.

Цель: интеграция с SOAP-сервисами или старыми системами, использующими XML-RPC.

Как установить Content-Type для multipart/form-data при отправке файлов?

Если в массиве, переданном в CURLOPT_POSTFIELDS, содержатся объекты CURLFile, cURL автоматически устанавливает заголовок multipart/form-data и генерирует границу. Принудительное указание Content-Type через CURLOPT_HTTPHEADER не рекомендуется, так как граница будет отсутствовать.


$ch = curl_init('https://example.com/upload');
curl_setopt($ch, CURLOPT_POST, 1);
$file = new CURLFile('/path/to/file.jpg', 'image/jpeg', 'photo.jpg');
$data = ['photo' => $file, 'description' => 'My photo'];
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
$response = curl_exec($ch);
  

Ошибка: если вместе с файлом передать и строку JSON (например, для поля metadata), cURL воспримет всю строку как multipart/form-data, но значение этого поля будет простой строкой, а не JSON. Сервер может ожидать JSON внутри части multipart. Решение: не смешивать типы без необходимости, либо кодировать JSON как строковое поле.

Случай использования: загрузка файлов на сервер через веб-формы.

Расширенные примеры установки Content-Type в cURL

Пример 1. Полный цикл отправки JSON с обработкой ответа и проверкой ошибок

Пример

$url = 'https://jsonplaceholder.typicode.com/posts';
$data = ['title' => 'foo', 'body' => 'bar', 'userId' => 1];
$jsonData = json_encode($data);

$ch = curl_init($url);
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => $jsonData,
    CURLOPT_HTTPHEADER => [
        'Content-Type: application/json',
        'Accept: application/json'
    ],
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT => 30
]);

$response = curl_exec($ch);
$info = curl_getinfo($ch);
$error = curl_error($ch);
curl_close($ch);

if ($error) {
    echo "cURL Error: $error";
} else {
    echo "HTTP Status: {$info['http_code']}\n";
    echo "Response: $response";
}
  
HTTP Status: 201
Response: {
  "title": "foo",
  "body": "bar",
  "userId": 1,
  "id": 101
}
  

Здесь показана полная обработка: проверка на ошибки cURL, получение HTTP-статуса, вывод тела ответа. Установка Accept позволяет серверу вернуть данные в нужном формате.

Пример 2. Отправка данных с файлом и полями формы (multipart/form-data)

Пример

$url = 'https://httpbin.org/post';
$file = new CURLFile('/tmp/test.txt', 'text/plain', 'document.txt');
$fields = ['name' => 'Alice', 'file' => $file];

$ch = curl_init($url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $fields);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);

$decoded = json_decode($response, true);
echo "Form data: " . print_r($decoded['form'], true);
echo "Files: " . print_r($decoded['files'], true);
  
Form data: Array
(
    [name] => Alice
)
Files: Array
(
    [file] => Array
        (
            [name] => document.txt
            [type] => text/plain
            [size] => 100
        )
)
  

Content-Type автоматически стал multipart/form-data; boundary=... . Принудительно изменять его не нужно - cURL сам формирует правильный заголовок.

Пример 3. PUT запрос с JSON данными и переопределением Content-Type

Пример

$url = 'https://api.example.com/resource/123';
$data = ['status' => 'updated'];
$ch = curl_init($url);
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'PUT',
    CURLOPT_POSTFIELDS => json_encode($data),
    CURLOPT_HTTPHEADER => [
        'Content-Type: application/json',
        'If-Match: "abc123"'
    ],
    CURLOPT_RETURNTRANSFER => true
]);
$response = curl_exec($ch);
curl_close($ch);
  

Для PUT запроса используется CURLOPT_CUSTOMREQUEST. Content-Type задаётся через CURLOPT_HTTPHEADER, как и в POST. Важно: не забыть кодировать данные.

Пример 4. Установка Content-Type с кодировкой (charset)

Пример

$ch = curl_init('https://example.com/text');
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, 'Простой текст на русском');
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    'Content-Type: text/plain; charset=utf-8'
]);
$response = curl_exec($ch);
  

Иногда требуется указать кодировку вместе с типом контента. Это делается добавлением параметра charset к значению заголовка. cURL не проверяет корректность кодировки - она просто передаётся на сервер.

Пример 5. Проверка фактического отправленного Content-Type через curl_getinfo

Пример

$ch = curl_init('https://httpbin.org/post');
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => 'key=value',
    CURLOPT_HTTPHEADER => ['Content-Type: application/x-www-form-urlencoded'],
    CURLOPT_RETURNTRANSFER => true
]);
$response = curl_exec($ch);
$info = curl_getinfo($ch);
curl_close($ch);
// In httpbin response we can see headers sent
echo "Sent Content-Type: " . json_decode($response, true)['headers']['Content-Type'];
  
Sent Content-Type: application/x-www-form-urlencoded
  

Это полезно для отладки: можно убедиться, что заголовок отправлен корректно.

Установка Content-Type в cURL в PHP - comments

En
Php curl content type (php)