← Back to Blog
Technical2026-10-27·Digital Footprint Health Team

Writing a Tweet Deletion Script with the X API: Tokens, Scopes, and Refresh

X APIdeletion scripttoken authdata privacylocal processing

If you want to bulk-delete years of old tweets, the first search result is usually a "deletion script," and the first thing people get stuck on is how to log that script into their X account. API auth looks intimidating, but it really comes down to three questions: where does the token come from, how long does it last, and what can it delete. Once those are clear, the deletion logic is the easy part.

What the API can and cannot delete

Let me set the limits up front so you do not waste effort. X's API has hard gates on deletion. The Free tier basically cannot get delete permission, and calling the delete endpoint returns 403. To remove tweets you usually need Pro or higher, with user-context authorization. The API only deletes tweets under your own account - not other people's, and not quoted snippets someone else wrote.

There is also the old limit people forget: through the API you can only reach tweets within your most recent 3,200. For anything older, download the full archive first, then operate on the tweet IDs inside it. The archive and the API are two tools that work together: the archive pulls out the old data, the API deletes by ID. Not an either/or.

Here is the practical catch: if your account has tens of thousands of tweets and you want to clear 2015 posts, API pagination alone will never reach that far. You need the archive first. A lot of people assume a script will just sweep everything, then get stuck because it literally cannot read data that old.

Three kinds of tokens, do not grab the wrong one

Auth centers on the token. Different flows issue different tokens, and the wrong one always returns 401.

Token typeHow you get itCan it delete?Who it fits
App-only BearerGenerated in the developer consoleNoRead-only analytics
User Context (OAuth 1.0a)Exchanged after user authorizationYesDeleting your own tweets
OAuth 2.0 user contextAuthorization-code flowYes (with the right scope)New apps, web clients

If you just want to delete your own old tweets, the user-context path is the most reliable. The app-only token looks simpler, but it carries the app's identity, not yours, so the delete endpoint rejects it. The difference is easy to spot: an app token has a fixed prefix and lives only in app config, while a user token is bound to a specific account after authorization.

Scopes: how to avoid a 401

OAuth 2.0 asks you to declare a scope at authorization. Deleting tweets needs both tweet.read and tweet.write. Leave either out and you will authorize fine but fail the moment you call delete. A common slip is writing read as readonly, or dropping write entirely. It is an annoying error: the consent screen said yes, yet the code says no permission.

One practical habit: after authorization, print the granted scope and confirm read and write are both there before writing any deletion code. It takes 30 seconds and saves an hour of debugging later. If the response has read but no write, go back through the auth flow again - do not hack around it in code.

Tokens expire, and refresh beats re-authorizing

User tokens are not forever. OAuth 1.0a tokens last a long time; OAuth 2.0 access tokens often expire in a few hours and need a refresh token to renew. Baking the refresh step into the script is far less annoying than re-authorizing by hand every time.

Two caveats. First, store the refresh token safely - it is just as sensitive as the access token. Second, in some setups a refresh invalidates the old access token immediately. In the script, swap to the new token, verify it works, then write it back locally. Do not crash mid-refresh and lose both.

A minimal working example

Here is the shape of it (pseudocode); watch the structure rather than any one line. Real endpoint names follow the official docs.

  • Exchange the stored refresh token for a fresh access token;
  • Read the target tweet-ID list from your archive or database;
  • Call the delete endpoint within the hourly rate limit;
  • Log successes, retry failures with backoff;
  • Emit a deletion report when done.

Rate limits are where beginners trip. Each endpoint has its own quota, and delete and read are counted separately. The table below shows common tiers; your actual numbers depend on your account level:

OperationRough limitOver-limit result
Read one tweetHundreds per 15 min429, must wait
Delete a tweetTens per 15 min429, must back off
Bulk read timelineEven lowerLikely throttled

Sleep briefly after each deletion, or adjust speed from the remaining-quota header, instead of firing requests in parallel. Higher concurrency does not mean faster; it tends to trip throttling and slow the whole run down.

Keep the secrets on your own machine

The most important point: tokens, refresh tokens, and API keys live only on your local disk. Do not paste them into a script you plan to share, and never commit them to a public repo. A frequent mistake is pushing a keyed script to GitHub, where bots scrape it within hours and the account gets banned.

If you would rather not wire up the whole auth flow yourself, a local tool works too: upload your X archive, parse it on your machine, mark the tweets you want gone, then decide whether to delete through the API. The keys never leave your computer, which cuts the risk down a lot. Even if the last step uses the API, the parsing and filtering happen locally, so sensitive data is never uploaded.

Common errors and how to handle them

Even with auth sorted, you can still hit a few fixed errors when deleting. A 401 means the token expired or the scope is wrong: swap the token, then re-check the scope. A 403 usually means the tier is too low; the Free tier always fails on delete, so you need Pro or higher. A 429 means you hit the rate limit; back off a few seconds using the remaining-quota header instead of pushing through. Log these three errors and their handling, and you can see at a glance where the run got stuck.

One more easily missed point: the delete endpoint sometimes returns success while the tweet is still there. When that happens, do not immediately retry the same tweet; query its status on its own to confirm whether it was really deleted or just a blip. Adding a verify-after-delete step to the script is steadier than blind retries, and it avoids hammering the same tweet and burning the whole rate budget.

digital-footprint-health.shop is a privacy-check tool that runs on your own machine. It parses your X archive, builds a risk list, and lets you delete risky tweets one by one, with the data never leaving your computer. See the homepage for how it works, or the blog for more data-safety practices.

Frequently Asked Questions

Can a free X account delete tweets through the API?

Almost never. The delete endpoint requires Pro or a higher tier; the Free tier is mostly read-only and returns 403 on delete.

Why can an app token not delete my tweets?

An app token carries the app identity, not yours. Deletion requires a user-context token issued after you authorize.

Why do I still get 401 after a successful authorization?

Usually the scope is missing tweet.write, or read/write is misspelled versus the official names. Print the scope after auth to check.

Do I have to re-authorize by hand when a token expires?

OAuth 2.0 can renew automatically with a refresh token if you put the logic in the script. OAuth 1.0a tokens last much longer.

How should I store secrets used by the script?

Keep them in a local file only, never in version control or shared snippets, and do not print raw tokens in logs.

Check your own X/Twitter footprint

Free on-device scan. Your archive never leaves your computer.

Start Free Check

Related Reads

Published on 2026-10-27. Last updated 2026-10-27.