How to upload images via PHP to Telegram bot API?

I’m trying to send pictures through my Telegram bot using PHP and cURL but running into issues. The documentation mentions that the photo parameter can be either a file_id string or an InputFile object uploaded via multipart/form-data.

Here’s my current approach:

$api_endpoint = "https://api.telegram.org/bot<token>/";
$request_url = $api_endpoint . "sendPhoto?chat_id=" . $user_id;
$curl_handle = curl_init();
curl_setopt($curl_handle, CURLOPT_HTTPHEADER, array(
    "Content-Type:multipart/form-data"
));
curl_setopt($curl_handle, CURLOPT_URL, $request_url);
curl_setopt($curl_handle, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl_handle, CURLOPT_POSTFIELDS, array(
    "photo" => "@/local/path/picture.jpg",
));
curl_setopt($curl_handle, CURLOPT_INFILESIZE, filesize("/home/user/image.jpg"));
$response = curl_exec($curl_handle);

When I run this code, Telegram responds with an error about wrong file_id characters or length. I also attempted using file_get_contents instead of the @ symbol, but that gives me empty responses.

What’s the correct method to upload image files to Telegram using PHP and cURL?

you’re overcomplicating this. just use file_get_contents to read the image into a variable then pass it as binary data. ‘photo’ => curl_file_create(‘/path/to/image.jpg’) works better than the old @ syntax. also remove that CURLOPT_INFILESIZE line - it’s not needed and might be messing with telegram’s parser.

The @ symbol approach is deprecated in newer PHP versions. Use CURLFile instead. Replace your photo parameter with new CURLFile('/local/path/picture.jpg', 'image/jpeg', 'photo.jpg'). Also drop the Content-Type header - cURL handles multipart headers automatically when you pass an array to POSTFIELDS. Make sure your file path is absolute and the web server can access it. I had the same issues until I switched to CURLFile - it handles file uploads properly and Telegram accepts them without complaints. Also check your file permissions are set correctly, that tripped me up too.

Had the same issue with Telegram photo uploads. You’re mixing GET and POST - putting chat_id in the URL but using POSTFIELDS won’t work. Here’s what fixed it for me: drop chat_id from the URL and add it to your POSTFIELDS array with the photo parameter. Set curl_setopt($curl_handle, CURLOPT_POST, true) to force POST method. Also, your file paths don’t match - you’ve got /local/path/picture.jpg in POSTFIELDS but /home/user/image.jpg for filesize. Pick one and make sure it’s the actual file location. This approach has been rock solid for me since I stopped mixing methods.