Skip to content

Instantly share code, notes, and snippets.

@baptx
Last active July 29, 2022 10:00
Show Gist options
  • Star 16 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save baptx/1525f338d93fa01db4e0 to your computer and use it in GitHub Desktop.
Save baptx/1525f338d93fa01db4e0 to your computer and use it in GitHub Desktop.
Twitter API 1.1 tweets / favorites (likes) / following / followers backup in web browser
/* Twitter API 1.1 tweets / favorites (likes) / following / followers backup in web browser
* Get your access keys to use Twitter API 1.1: https://dev.twitter.com/docs/auth/tokens-devtwittercom
* You can change Twitter API URL and Twitter screen_name, then execute script from a trusted web page without CSP protection like about:blank in a web browser console (F12 or Ctrl+Shift+K shortcut)
* A textarea will appear so you can copy/paste to save data as a CSV file or search tweets / users in your web browser (Ctrl+F shortcut)
* You can then view your backup in a spreadsheet editor like LibreOffice Calc
* You can also compare the backup with another one to see who unfollowed you, who changed their Twitter username by looking at the user ID or which tweet you retweeted / favorited was deleted (e.g. with the Linux diff command)
*
* Note about the tweets backup:
* Usually you will search tweets that you retweeted using Twitter web version (https://twitter.com/search) with a search like "from:your_username filter:nativeretweets keyword"
* But it is limited to the retweets of the last 7 days, like for the free version of the search API (https://developer.twitter.com/en/docs/tweets/search/overview/standard)
* An alternative is to search tweets in your user timeline with this script but it is limited to your last 3200 tweets (including retweets and replies)
* This script can be combined with the Twitter feature to backup data, which is not limited to your last 3200 tweets but you can only request a backup every 30 days
* To find tweets that you retweeted or favorited / liked from a specific person, you can open the CSV file with LibreOffice Calc, click on the column you want to search and press Ctrl+H to search a username
*/
var url = "https://api.twitter.com/1.1/statuses/user_timeline.json"
//var url = "https://api.twitter.com/1.1/favorites/list.json";
//var url = "https://api.twitter.com/1.1/friends/list.json";
//var url = "https://api.twitter.com/1.1/followers/list.json";
var accessor = {
token: "XXX",
tokenSecret: "XXX",
consumerKey : "XXX",
consumerSecret: "XXX"
};
var message = {
action: url,
method: "GET",
parameters: {
screen_name: "jack",
count: 200,
callback: "getJSONP"
}
};
var out = [];
var length = -1;
var start = 0;
var next = -1;
var res;
function getJSONP(data)
{
res = data;
}
function loadAPI_tweets()
{
if (length != 1)
{
if (next != -1) {
message.parameters.max_id = next;
}
OAuth.completeRequest(message, accessor);
OAuth.SignatureMethod.sign(message, accessor);
var script3 = document.createElement("script");
script3.setAttribute("src", url + '?' + OAuth.formEncode(message.parameters));
document.body.appendChild(script3);
script3.addEventListener("load", function() {
length = res.length;
for (var i = 0; i < length; ++i) {
var text, name, id;
if (res[i].retweeted_status) {
text = res[i].retweeted_status.full_text;
name = res[i].retweeted_status.user.screen_name;
id = res[i].retweeted_status.user.id;
} else {
text = res[i].full_text;
name = res[i].user.screen_name;
id = res[i].user.id;
}
out[start + i] = res[i].created_at + '\t'
+ name + '\t"""'
+ id + '"""\t"' // backup user ID to track a user who deleted a tweet you retweeted / favorited (even if the user changed his username)
+ text.replace(/"/g, '""') + '"\t"""'
+ res[i].id_str + '"""';
// CSV with tab separator: quote to allow multiline string; escape quote string delimiter with double quote; display large numbers correctly as string with triple quote
}
next = res[length - 1].id_str;
start += length - 1;
loadAPI_tweets();
});
}
else
{
displayData();
}
}
function loadAPI_users()
{
if (length == -1 || res.next_cursor_str != 0) {
message.parameters.cursor = next;
OAuth.completeRequest(message, accessor);
OAuth.SignatureMethod.sign(message, accessor);
var script3 = document.createElement("script");
script3.setAttribute("src", url + '?' + OAuth.formEncode(message.parameters));
document.body.appendChild(script3);
script3.addEventListener("load", function() {
length = res.users.length;
for (var i = 0; i < length; ++i) {
out[start + i] = res.users[i].screen_name + '\t'
+ res.users[i].name.replace(/"/g, '""') + '\t"""'
+ res.users[i].id + '"""';
}
next = res.next_cursor_str;
start += length;
loadAPI_users();
});
}
else {
displayData();
}
}
function displayData()
{
var box = document.createElement("textarea");
box.value = out.join('\n');
document.body.appendChild(box);
}
var script = document.createElement("script");
script.setAttribute("src", "https://pastebin.com/raw/HFjqYLdG"); // http://oauth.googlecode.com/svn/code/javascript/oauth.js (down)
document.body.appendChild(script);
script.addEventListener("load", function() {
var script2 = document.createElement("script");
script2.setAttribute("src", "https://pastebin.com/raw/M0N8JKwf"); // http://pajhome.org.uk/crypt/md5/sha1.js
document.head.appendChild(script2);
script2.addEventListener("load", function() {
if (url == "https://api.twitter.com/1.1/statuses/user_timeline.json" || url == "https://api.twitter.com/1.1/favorites/list.json") {
message.parameters.include_rts = true; // include retweets
message.parameters.tweet_mode = "extended"; // needed to get full tweet after API change
loadAPI_tweets();
}
else {
loadAPI_users();
}
});
});
@devmbm
Copy link

devmbm commented Nov 21, 2020

That is spot on 👌 thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment