I am currently writing a chatbot for WhatsApp. I use the 360dialog platform, which makes it possible to work with the WhatsApp Business API.

When the client sends a message, I see the following JSON object in the logs of my application:

{     "messages": [         {             "from": "77773336633",             "id": "ABGGd3c1cGY_Ago61ytHsZknvtLv",             "image": {                 "id": "ffd23134-2dae-4fed-b5f8-0ce7867b6ddd",                 "mime_type": "image/jpeg",                 "sha256": "bd02100d961b5a1dbaae1dd645485ebbfeda77b44e82c015f1cf29b05654ccb9"             },             "timestamp": "1605703542",             "type": "image"         }     ],     "contacts": [         {             "profile": {                 "name": "Nurzhan Nogerbek"             },             "wa_id": "77773336633"         }     ] } 

I can't find any information in the documentation about how to download this file. In my case, I want to upload this image file that the client sends to my file storage. Please tell me which URL method from the WhatsApp API is responsible for this mechanism?

P.S. At the same time, I can send files to clients. This information is available on the official documentation.

Tag:json, whatsapp

14 comments.

  1. SadikAli

    It was very tricky because postman worked, but c# didn't work for me, and I spent two days trying to find the solution and finally did the following code, which works in C#:

    using HttpClient _httpClient = new HttpClient(); Uri uri = new Uri(mediaUrl); var fileName = $"{DateTime.Now.ToString("yyyyMMddhhmmss")}.jpeg"; string filePath = $"Files\\{fileName}"; // NOTE: to save bandwidth, request compressed content _httpClient.DefaultRequestHeaders.AcceptEncoding.Clear(); _httpClient.DefaultRequestHeaders.AcceptEncoding.Add(new StringWithQualityHeaderValue("gzip")); _httpClient.DefaultRequestHeaders.AcceptEncoding.Add(new StringWithQualityHeaderValue("deflate")); _httpClient.DefaultRequestHeaders.AcceptEncoding.Add(new StringWithQualityHeaderValue("br")); // NOTE: accept all languages _httpClient.DefaultRequestHeaders.AcceptLanguage.Clear(); _httpClient.DefaultRequestHeaders.AcceptLanguage.Add(new StringWithQualityHeaderValue("*")); // NOTE: accept all media types _httpClient.DefaultRequestHeaders.Accept.Clear(); _httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("*/*")); _httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("image/jpeg")); var productValue = new ProductInfoHeaderValue("ScraperBot", "1.0"); var commentValue = new ProductInfoHeaderValue("(+http://www.API.com/ScraperBot.html)"); _httpClient.DefaultRequestHeaders.UserAgent.Add(productValue); _httpClient.DefaultRequestHeaders.UserAgent.Add(commentValue); _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", {WhatsApp_Access_Token}); HttpResponseMessage response = await _httpClient.GetAsync(uri); response.EnsureSuccessStatusCode(); var mediaType = response?.Content?.Headers?.ContentType?.MediaType ?? string.Empty; var imageBytes = await response.Content.ReadAsByteArrayAsync(); using (var fs = new FileStream(filePath, FileMode.Create, FileAccess.Write)) { fs.Write(imageBytes, 0, imageBytes.Length); }

    Here, {WhatsApp_Access_Token} is your Whatsapp API permanent token.

    Ping me in a comment, please, if you have any issues or questions.

    1. user2455808

      This is the best solution, but I have been purposely avoiding it due to the web scraping. I found the proper user agent needs to be: _httpClient.DefaultRequestHeaders.UserAgent.ParseAdd("WhatsApp/2.19.81 A");

  2. Dhia Djobbi

    May be it will help, just try, take a look:-

    const URL = `https://lookaside.fbsbx.com/whatsapp_business/attachments/?mid=1104480873777230&ext=1662705250&hash=ATuMx352sLrhKUegbQZSC8oLl3J5Vy3Z49lO4HwTUKWRYQ`; const FROM = `video`; const config = { method: 'get', url: URL, //PASS THE URL HERE, WHICH YOU RECEIVED WITH THE HELP OF MEDIA ID headers: { 'Authorization': `Bearer ${token}` }, responseType: 'arraybuffer' }; axios(config) .then(function (response) { const ext = response.headers['content-type'].split("/")[1]; fs.writeFileSync(`${FROM}.${ext}`, response.data); }) .catch(function (error) { console.log(error); });
    1. Rupak

      I am getting json in console.log(ext), can you help me with this

  3. Max

    I saw this thread and it finally helped me getting the solution. Here is the entire C# code from retrieving a media id inside the whatsapp message. The problem without the agent is that facebook responds with a message that the browser is not supported without it.

    string whatsappBaseUrl = "https://graph.facebook.com/v15.0/"; string mediaId = "id you received in message"; string accesstoken = "Your Whatsapp Access Token"; string agentHeader = "WhatsApp/2.19.81 A"; _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accesstoken); string url = $"{whatsappBaseUrl}{mediaId}"; var getMediaUrl = await _httpClient.GetAsync(url); if (getMediaUrl.IsSuccessStatusCode) { _httpClient.DefaultRequestHeaders.UserAgent.ParseAdd(agentHeader); var response = await _httpClient.GetByteArrayAsync(mediaUrl); Stream stream = new MemoryStream(response); }
    1. The Memebot

      this line of code was the key for me: string agentHeader = "WhatsApp/2.19.81 A";

    2. Immanuel

      what is this agent header, any documentation link?, I upvoted for the comment. it really helped.

  4. Fabio Castro

    For the entire message cycle (receiving the request, downloading the audio file, and transcribing it with OpenAI's Whisper), in Python:

    Define the function for retrieving the file, saving and transcribing:

    def retrieve_text(media_id, audio_name = 'received_audio'): url = f"https://graph.facebook.com/v17.0/{media_id}/" # the media id obtained in the webhook headers = {'Authorization': f'Bearer {access_token}' } # enter your access token here response = requests.get(url, headers=headers) # get the message file_url = response.json()['url'] # get the file url response = requests.get(file_url, headers=headers) # get the file binary open(audio_name+'.ogg', 'wb').write(response.content) # save the received file audio_file = open(audio_name+'.ogg', "rb") # open the file transcript = openai.Audio.transcribe("whisper-1", audio_file) # transcribe with OpenAI API return transcript.text # return the transcription

    Then, upon receiving the request in your Webhook:

    incoming_msg = request.json #messages = incoming_msg['entry'][0]['changes'][0]['value']['messages'][0] media_id = message[0]['audio']['id'] retrieve_text(media_id)
  5. Alan Facchini

    The official documentation has a session for this in https://developers.facebook.com/docs/whatsapp/api/media.

    Basically you must make a GET request to download the media.

    curl --request GET \ --url https://waba.360dialog.io/v1/media/{media id} \ --header 'D360-API-KEY: {your api token}'
    1. Edoardo

      With this were you able to solve? A very long string returns to me how can I save the image on the server?

    2. Federico Schiocchet

      this solution does not work.

    3. Alan Facchini

      The documentation has been modified and the new url is this developers.facebook.com/docs/whatsapp/api/media/media-id

    4. Alan Facchini

      When you make the request, the server will return a blob to you. You need to read that blob and assign it to a Buffer. (Buffer.from(response.data).toString('base64')) After that you can do whatever you want with the media content.

    5. nasiphi vinqishe

      @AlanFacchini using Axios I get a blank file, please help const fileContents = Buffer.from( mediaDownloadResults.data ).toString("base64"); fs.writeFile(document.id + ".pdf", fileContents, (err) => { if (err) return console.error(err); console.log("file saved to "); });

Add a new comment.