Skip to content

Instantly share code, notes, and snippets.

@lastbattle
Last active January 16, 2025 14:13
Show Gist options
  • Select an option

  • Save lastbattle/2541678dc308e93c97daa97506c76bf6 to your computer and use it in GitHub Desktop.

Select an option

Save lastbattle/2541678dc308e93c97daa97506c76bf6 to your computer and use it in GitHub Desktop.
Delete tweet

Original source: https://gist.github.com/apsun/d5a16275d7078c9c038b877adf292f28 Updated for the mac.

100% free. Runs completely locally on your machine. Bypasses the 3200 tweet limit. May require some eye bleach for the script. Here's how to use it:

Go to settings -> account -> your Twitter data and request a download. This may take a few hours. You'll get an email with a link to download a zip file. Extract the zip file and navigate to the data directory.

Go to Twitter in a web browser and find any Tweet you want to delete. We're going to use it to extract your authentication credentials for the next step. Open developer tools, delete the tweet, and find the request to https://twitter.com/i/api/graphql/.../DeleteTweet. Right click it and copy it as cURL.

Save delet_tweets.sh into your data directory. Open it in a text editor, and paste the command you got from the previous step where it says YOUR_CURL_COMMAND_HERE. Replace the id parameter for --data with $tweet_id (make sure to adjust quoting accordingly). Add --compressed as well to tell curl to un-gzip the response.

Let 'er rip. It will probably take a while (for me, somewhere around 10-20k tweets an hour), so leave it running in the background. If you want to see your deleted tweets as they go by, pipe the output of curl to jq -r .full_text (add -s to curl too).

#!/bin/bash
set -euo pipefail
# Check required commands
for cmd in jq sed curl date; do
command -v "$cmd" >/dev/null 2>&1 || { echo >&2 "Required command $cmd not found"; exit 1; }
done
DELETE_BEFORE="2024-01-01 00:00"
QUERY_ID="VaenaVgh5q5ih7kvyVjgtg" # Define the query ID
RATE_LIMIT_SECONDS=1 # Add rate limiting
# Convert date based on OS
if [[ "$OSTYPE" == "darwin"* ]]; then
target_timestamp=$(date -j -f "%Y-%m-%d %H:%M" "$DELETE_BEFORE" +%s)
else
target_timestamp=$(date -d "$DELETE_BEFORE" +%s)
fi
cat tweets.js \
| sed '1 s/window.YTD.tweets.part0 = //' \
| jq -r '.[] | [.tweet.id, (.tweet.created_at | strptime("%a %b %d %H:%M:%S %z %Y") | mktime)] | @tsv' \
| sort -k2 -n \
| awk -v d="$target_timestamp" '$2 < d { print $1 }' \
| while read -r tweet_id; do
# Skip empty lines
[ -z "$tweet_id" ] && continue
echo "Deleting tweet $tweet_id..."
# Make the API call
response=$(YOUR_CURL_COMMAND_HERE
--data-raw "{\"variables\":{\"tweet_id\":\"${tweet_id}\",\"dark_request\":false},\"queryId\":\"${QUERY_ID}\"}"
) || { echo "Failed to delete tweet $tweet_id"; continue; }
# Check response
if echo "$response" | jq -e '.errors' >/dev/null; then
echo "Error deleting tweet $tweet_id: $(echo "$response" | jq -r '.errors[0].message')"
else
echo "Successfully deleted tweet $tweet_id"
fi
# Rate limiting
sleep "$RATE_LIMIT_SECONDS"
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment