Другое

Почему PHP cURL возвращает ошибку 'malformed' при запросе к Telegram API

Устраняем ошибку 'malformed' в PHP cURL запросах к Telegram API. Узнайте о проблемах с кодировкой URL, настройках cURL и правильной реализации запросов к Telegram API.

Почему перестал работать PHP cURL запрос к Telegram API? Код выполняется без ошибок, но возвращает ошибку ‘malformed’. При этом прямой запрос из браузера к тому же URL работает корректно. Функция parser() использует cURL для отправки запроса к Telegram API, но перестала работать после того как раньше работала. В чем может быть проблема и как это исправить? Код функции:

php
function parser($url){
    $curl = curl_init();
    curl_setopt($curl, CURLOPT_URL, $url);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
    $result = curl_exec($curl);
    if($result == false){ 
      echo "Ошибка отправки запроса: " . curl_error($curl);
      return false;
    }
    else{
      return true;
    }
}

parser("https://api.telegram.org/bot{$token}/sendPhoto?chat_id={$chat_id}&caption=text&photo=https://site.ru/bot/image_avatar/0001.jpg");

При вызове функции выводится ошибка: ‘Ошибка отправки запроса: malformed’. Проверка сервера показала, что настройки не менялись. Может ли проблема быть в конфигурации PHP или cURL?

The “malformed” error in your PHP cURL request to Telegram API typically occurs due to URL encoding issues, cURL configuration problems, or character encoding mismatches. Based on the research findings and your code, here are the most likely causes and solutions:

Contents

Common Causes of ‘malformed’ Error

The “cURL error 3: malformed” error occurs when cURL cannot properly parse the URL you’re trying to request. This can happen for several reasons:

  1. Special characters in URLs - Spaces, Cyrillic characters, or other special characters that aren’t properly encoded
  2. Malformed URL structure - Incorrect formatting of query parameters
  3. cURL configuration issues - Missing or incorrect cURL options
  4. PHP version incompatibilities - Changes in how PHP handles URLs or cURL
  5. SSL/TLS certificate problems - Issues with certificate verification

In your case, the problem is likely in the URL construction where the caption=text parameter contains unencoded characters.

URL Encoding Issues

The most common cause of the “malformed” error is improper URL encoding. According to the research findings, spaces and special characters in URLs are a frequent culprit.

Problem in your code:

php
parser("https://api.telegram.org/bot{$token}/sendPhoto?chat_id={$chat_id}&caption=text&photo=https://site.ru/bot/image_avatar/0001.jpg");

The caption=text parameter might contain spaces or special characters that need to be URL-encoded. Additionally, the photo URL itself should be properly encoded.

Solution:
Use urlencode() for all URL parameters:

php
function parser($url){
    $curl = curl_init();
    curl_setopt($curl, CURLOPT_URL, $url);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
    $result = curl_exec($curl);
    if($result == false){ 
      echo "Ошибка отправки запроса: " . curl_error($curl);
      return false;
    }
    else{
      return true;
    }
}

// Proper URL encoding
$encoded_caption = urlencode($text);
$encoded_photo_url = urlencode($photo_url);
$url = "https://api.telegram.org/bot{$token}/sendPhoto?chat_id={$chat_id}&caption={$encoded_caption}&photo={$encoded_photo_url}";

parser($url);

cURL Configuration Problems

Several research sources indicate that cURL configuration issues can cause “malformed” errors. Here are the essential cURL options that should be set for Telegram API requests:

Missing configuration options:

php
function parser($url){
    $curl = curl_init();
    curl_setopt($curl, CURLOPT_URL, $url);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
    
    // Add these essential options:
    curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
    curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); // For testing
    curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false); // For testing
    curl_setopt($curl, CURLOPT_USERAGENT, 'Mozilla/5.0 (compatible; Telegram Bot API)');
    curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 10);
    curl_setopt($curl, CURLOPT_TIMEOUT, 30);
    
    $result = curl_exec($curl);
    if($result == false){ 
      echo "Ошибка отправки запроса: " . curl_error($curl);
      return false;
    }
    else{
      return true;
    }
}

According to the research, SSL certificate issues are a common problem that can manifest as various cURL errors, including “malformed”.

Character Encoding and SSL Issues

Character encoding problems:
Telegram API requires UTF-8 encoding. If your text contains Cyrillic characters or other non-ASCII characters, they need to be properly handled:

php
// Set proper character encoding
mb_internal_encoding('UTF-8');

// Ensure text is UTF-8
$text = mb_convert_encoding($text, 'UTF-8', 'UTF-8');

SSL certificate issues:
If you’re having SSL problems, you can temporarily disable SSL verification for testing (but not for production):

php
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);

Practical Solutions

Based on the research findings, here are the most effective solutions:

1. Use Proper URL Encoding

Always encode URL parameters:

php
$token = 'your_bot_token';
$chat_id = 'your_chat_id';
$text = 'Your caption with spaces';
$photo_url = 'https://site.ru/bot/image_avatar/0001.jpg';

$url = sprintf(
    'https://api.telegram.org/bot%s/sendPhoto?chat_id=%s&caption=%s&photo=%s',
    urlencode($token),
    urlencode($chat_id),
    urlencode($text),
    urlencode($photo_url)
);

2. Use POST Method for File Uploads

For sending photos, it’s better to use POST method with proper file handling:

php
function sendPhotoToTelegram($token, $chat_id, $caption, $photo_path) {
    $url = "https://api.telegram.org/bot{$token}/sendPhoto";
    
    $cfile = new CURLFile(realpath($photo_path), 'image/jpeg', basename($photo_path));
    
    $data = [
        'chat_id' => $chat_id,
        'caption' => $caption,
        'photo' => $cfile
    ];
    
    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    
    $result = curl_exec($ch);
    $error = curl_error($ch);
    curl_close($ch);
    
    if ($result === false) {
        echo "Ошибка отправки запроса: " . $error;
        return false;
    }
    
    return json_decode($result, true);
}

3. Check PHP and cURL Versions

Ensure you have compatible versions:

php
echo 'PHP Version: ' . phpversion() . "\n";
echo 'cURL Version: ' . curl_version()['version'] . "\n";

Complete Working Implementation

Here’s a complete, robust implementation that addresses all the common issues:

php
function sendTelegramMessage($token, $chat_id, $text, $parse_mode = 'HTML') {
    $url = "https://api.telegram.org/bot{$token}/sendMessage";
    
    $data = [
        'chat_id' => $chat_id,
        'text' => $text,
        'parse_mode' => $parse_mode
    ];
    
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
    curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (compatible; Telegram Bot API)');
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
    curl_setopt($ch, CURLOPT_TIMEOUT, 30);
    
    $result = curl_exec($ch);
    $error = curl_error($ch);
    curl_close($ch);
    
    if ($result === false) {
        throw new Exception("Ошибка отправки запроса: " . $error);
    }
    
    $response = json_decode($result, true);
    
    if (!$response || !$response['ok']) {
        throw new Exception("Ошибка Telegram API: " . ($response['description'] ?? 'Unknown error'));
    }
    
    return $response;
}

function sendTelegramPhoto($token, $chat_id, $photo_path, $caption = '', $parse_mode = 'HTML') {
    $url = "https://api.telegram.org/bot{$token}/sendPhoto";
    
    if (!file_exists($photo_path)) {
        throw new Exception("Файл не найден: " . $photo_path);
    }
    
    $file_info = new CURLFile(realpath($photo_path), mime_content_type($photo_path), basename($photo_path));
    
    $data = [
        'chat_id' => $chat_id,
        'photo' => $file_info,
        'caption' => $caption,
        'parse_mode' => $parse_mode
    ];
    
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
    curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (compatible; Telegram Bot API)');
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
    curl_setopt($ch, CURLOPT_TIMEOUT, 30);
    
    $result = curl_exec($ch);
    $error = curl_error($ch);
    curl_close($ch);
    
    if ($result === false) {
        throw new Exception("Ошибка отправки запроса: " . $error);
    }
    
    $response = json_decode($result, true);
    
    if (!$response || !$response['ok']) {
        throw new Exception("Ошибка Telegram API: " . ($response['description'] ?? 'Unknown error'));
    }
    
    return $response;
}

// Usage examples:
try {
    // Send text message
    sendTelegramMessage($token, $chat_id, 'Hello World!');
    
    // Send photo with caption
    sendTelegramPhoto($token, $chat_id, '/path/to/photo.jpg', 'This is a caption');
} catch (Exception $e) {
    echo "Ошибка: " . $e->getMessage();
}

Sources

  1. Stack Overflow - Telegram bot send message from server failed PHP
  2. Stack Overflow - sending message in telegram bot using curl
  3. BobCares - cURL error 3 url malformed : How we fix it
  4. Stack Overflow - Guzzle returns cURL error 3: malformed
  5. Reddit - Malformed URL in PHP API Call [Guzzle]

Conclusion

The “malformed” error in your PHP cURL request to Telegram API is typically caused by:

  1. Improper URL encoding - Use urlencode() for all parameters
  2. Missing cURL options - Add SSL, timeout, and user agent settings
  3. Character encoding issues - Ensure UTF-8 encoding
  4. Incorrect HTTP method - Use POST for file uploads instead of GET

Start by implementing proper URL encoding and adding the essential cURL options. If you’re still experiencing issues, consider switching to the POST method for file uploads as shown in the complete implementation above. Always handle errors properly and validate responses from the Telegram API to get detailed error messages.

Авторы
Проверено модерацией
Модерация