Advertisement
baptx

instagram-api_direct_messages_backup

Sep 14th, 2019 (edited)
6,521
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /*
  2. Instagram API: view and backup direct messages from a web browser
  3.  
  4. Since April 2020, Instagram has a web version to send and read direct messages so my Instagram scripts are not longer needed and I would not recommend using them unless you really need it, to avoid being banned
  5. (never happened to me with Instagram but WhatsApp is owned by Facebook also and they did it to users registering from an unofficial app like yowsup: https://github.com/tgalal/yowsup/commit/88b8ad9581fa22dac330ee3a05fec4e485dfa634#diff-b335630551682c19a781afebcf4d07bf978fb1f8ac04c6bf87428ed5106870f5)
  6.  
  7. 1) Log in on Instagram web version and go to your profile page
  8. (the home page will not work because it loads data when scrolling down and the direct messages will be displayed at the bottom of the page)
  9.  
  10. 2) Modify HTTP headers with a browser addon like Header Editor (https://addons.mozilla.org/en-US/firefox/addon/header-editor/)
  11.  
  12. Content-Security-Policy (response header on domain www.instagram.com): original data with https://i.instagram.com/ added to connect-src
  13. report-uri https://www.instagram.com/security/csp_report/; default-src 'self' https://www.instagram.com; img-src https: data: blob:; font-src https: data:; media-src 'self' blob: https://www.instagram.com https://*.cdninstagram.com https://*.fbcdn.net; manifest-src 'self' https://www.instagram.com; script-src 'self' https://instagram.com https://www.instagram.com https://*.www.instagram.com https://*.cdninstagram.com wss://www.instagram.com https://*.facebook.com https://*.fbcdn.net https://*.facebook.net 'unsafe-inline' 'unsafe-eval' blob:; style-src 'self' https://*.www.instagram.com https://www.instagram.com 'unsafe-inline'; connect-src 'self' https://instagram.com https://www.instagram.com https://i.instagram.com https://*.www.instagram.com https://graph.instagram.com https://*.graph.instagram.com https://*.cdninstagram.com https://api.instagram.com wss://www.instagram.com wss://edge-chat.instagram.com https://*.facebook.com https://*.fbcdn.net https://*.facebook.net chrome-extension://boadgeojelhgndaghljhdicfkmllpafd blob:; worker-src 'self' blob: https://www.instagram.com; frame-src 'self' https://instagram.com https://www.instagram.com https://staticxx.facebook.com https://www.facebook.com https://web.facebook.com https://connect.facebook.net https://m.facebook.com; object-src 'none'; upgrade-insecure-requests
  14.  
  15. User-Agent (request header on domain i.instagram.com)
  16. Instagram 85.0.0.21.100 Android (23/6.0.1; 538dpi; 1440x2560; LGE; LG-E425f; vee3e; en_US)
  17.  
  18. 3) Run the following JavaScript code in the web console of your browser or in a tool like Firefox scratchpad.
  19. The function InstagramDMthreads should be used first, then you have to comment the call to it and uncoment the call to InstagramDMmessages,
  20. which takes a thread ID as parameter (found with the previous function InstagramDMthreads).
  21. A textarea will appear to the bottom of the page so you can copy-paste to backup data (if you don't see it, you have to close the web console or scroll down).
  22.  
  23. If you want to send direct messages without using Android / iOS and the official proprietary app, you can use open source desktop apps like IG:dm, do cURL requests to the API or use my web browser script instagram-api_send_message.js.
  24. */
  25.  
  26. /* Usage */
  27. //InstagramDMthreads();
  28. //InstagramDMmessages("XXX"); // parameter needs to be a string since it is too big for an integer
  29.  
  30. /* CONFIG */
  31. var backup = true; // if backup is set to false, only the last threads and messages are displayed, in browser console instead of textarea (number can be configured in limit variable)
  32. var limit = 100; // 20 threads and messages by default, per API request
  33. /* END CONFIG */
  34.  
  35. var start;
  36. var data;
  37. var usernames;
  38.  
  39. // backup will return: thread ID, date + time + timezone, userid, username, last message
  40. function InstagramDMthreads()
  41. {
  42.     initVariables(); // clear variables to allow reusing functions several time
  43.    
  44.     var xhr = new XMLHttpRequest();
  45.     xhr.open("GET", "https://i.instagram.com/api/v1/direct_v2/inbox/" + "?limit=" + limit);
  46.     xhr.withCredentials = true;
  47.     xhr.addEventListener("load", function() {
  48.         var response = JSON.parse(xhr.responseText);
  49.         if (backup) {
  50.             scrollInbox(response);
  51.         }
  52.         else {
  53.             parseInbox(response);
  54.             console.log(data);
  55.         }
  56.     });
  57.     xhr.send();
  58. }
  59.  
  60. function parseInbox(response)
  61. {
  62.     var length = response.inbox.threads.length;
  63.     for (var i = 0; i < length; ++i) {
  64.         // length is 0 for conversations with yourself
  65.         var userid = response.inbox.threads[i].users.length != 0 ? response.inbox.threads[i].users[0].pk : response.viewer.pk;
  66.         var username = response.inbox.threads[i].users.length != 0 ? response.inbox.threads[i].users[0].username : response.viewer.username;
  67.         data[start + i] = '"""' + response.inbox.threads[i].thread_id + '"""\t'
  68.             + new Date(response.inbox.threads[i].last_activity_at / 1000).toString() + '\t'
  69.             + userid + '\t'
  70.             + username + '\t'
  71.             + '"' + getMessageText(response.inbox.threads[i].items[0]).replace(/"/g, '""') + '"';
  72.             // allow multiline CSV string with tab separator and escape double quote string delimiter
  73.     }
  74.     start += length;
  75. }
  76.  
  77. function scrollInbox(response)
  78. {
  79.     parseInbox(response);
  80.    
  81.     var cursor = response.inbox.oldest_cursor;
  82.    
  83.     if (cursor) {
  84.         var xhr = new XMLHttpRequest();
  85.         xhr.open("GET", "https://i.instagram.com/api/v1/direct_v2/inbox/?cursor=" + cursor + "&limit=" + limit);
  86.         xhr.withCredentials = true;
  87.         xhr.addEventListener("load", function() {
  88.             var response = JSON.parse(xhr.responseText);
  89.             scrollInbox(response);
  90.         });
  91.         xhr.send();
  92.     }
  93.     else {
  94.         displayData();
  95.     }
  96. }
  97.  
  98. // backup will return: date + time + timezone, username, message
  99. function InstagramDMmessages(thread)
  100. {
  101.     initVariables(); // clear variables to allow reusing functions several time
  102.    
  103.     var xhr = new XMLHttpRequest();
  104.     xhr.open("GET", "https://i.instagram.com/api/v1/direct_v2/threads/" + thread + "/" + "?limit=" + limit);
  105.     xhr.withCredentials = true;
  106.     xhr.addEventListener("load", function() {
  107.         var response = JSON.parse(xhr.responseText);
  108.        
  109.         var xhr2 = new XMLHttpRequest();
  110.         xhr2.open("GET", "https://i.instagram.com/api/v1/users/" + response.thread.viewer_id + "/info/");
  111.         xhr2.withCredentials = true;
  112.         xhr2.addEventListener("load", function() {
  113.             var response2 = JSON.parse(xhr2.responseText);
  114.            
  115.             usernames[response.thread.viewer_id] = response2.user.username;
  116.             usernames[response.thread.users[0].pk] = response.thread.users[0].username;
  117.            
  118.             if (backup) {
  119.                 scrollThread(thread, response);
  120.             }
  121.             else {
  122.                 parseThread(thread, response);
  123.                 console.log(data);
  124.             }
  125.         });
  126.         xhr2.send();
  127.     });
  128.     xhr.send();
  129. }
  130.  
  131. function parseThread(thread, response)
  132. {
  133.     var length = response.thread.items.length;
  134.     for (var i = 0; i < length; ++i) {
  135.         data[start + i] = new Date(response.thread.items[i].timestamp  / 1000).toString() + '\t'
  136.             + usernames[response.thread.items[i].user_id] + '\t'
  137.             + '"' + getMessageText(response.thread.items[i]).replace(/"/g, '""') + '"';
  138.     }
  139.     start += length;
  140. }
  141.  
  142. function scrollThread(thread, response)
  143. {
  144.     parseThread(thread, response);
  145.    
  146.     if (response.thread.prev_cursor != "MINCURSOR") {
  147.         var cursor = response.thread.oldest_cursor;
  148.        
  149.         var xhr = new XMLHttpRequest();
  150.         xhr.open("GET", "https://i.instagram.com/api/v1/direct_v2/threads/" + thread + "/?cursor=" + cursor + "&limit=" + limit);
  151.         xhr.withCredentials = true;
  152.         xhr.addEventListener("load", function() {
  153.             var response = JSON.parse(xhr.responseText);
  154.             scrollThread(thread, response);
  155.         });
  156.         xhr.send();
  157.     }
  158.     else {
  159.         displayData();
  160.     }
  161. }
  162.  
  163. function getMessageText(item)
  164. {
  165.     var type = item.item_type;
  166.     var text;
  167.    
  168.     switch (type) {
  169.         case "text":
  170.             text = item.text;
  171.             break;
  172.         case "link": // used if the message contains a link
  173.             text = item.link.text;
  174.             break;
  175.         case "action_log": // used when someone likes a message
  176.             text = item.action_log.description;
  177.             break;
  178.         case "like": // used when someone sends a like
  179.             text = item.like;
  180.             break;
  181.         case "media":
  182.             if (item.media.media_type == 1) {
  183.                 text = item.media.image_versions2.candidates[0].url;
  184.             }
  185.             else { // media_type is 1 for images and 2 for videos
  186.                 text = item.media.video_versions[0].url;
  187.             }
  188.             break;
  189.         case "animated_media": // for GIF files
  190.             text = item.animated_media.images.fixed_height.url;
  191.             break;
  192.         case "voice_media": // for audio recordings
  193.             text = item.voice_media.media.audio.audio_src;
  194.             break;
  195.     }
  196.    
  197.     return text;
  198. }
  199.  
  200. function initVariables()
  201. {
  202.     start = 0;
  203.     data = [];
  204.     usernames = [];
  205. }
  206.  
  207. function displayData()
  208. {
  209.     var box = document.createElement("textarea");
  210.     box.value = data.join("\n");
  211.     document.body.appendChild(box);
  212. }
  213.  
Advertisement
RAW Paste Data Copied
Advertisement