TwitterAPIs Docs
API ReferenceWrite Actions

Update Banner API

Replace the wide header image on the account behind your registered session. Send the image base64-encoded in the request body; there is no URL-fetch form and no multipart form. Billed at $0.0016 per call. Cost: $0.0016 per call.

POST user/update_banner replaces the wide header image on the account behind your registered twitterapis session. It takes one field, banner, holding the base64-encoded image bytes, and returns ok. The change is immediate and has no undo, so read your current cover_picture with user/info first if you may want it back. It costs $0.0016 a call.

POST
/user/update_banner

Authorization

bearerAuth
AuthorizationBearer <token>

Pass your API key as a bearer token on every request: Authorization: Bearer <API_KEY>.

In: header

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

Response Body

application/json

application/json

application/json

application/json

application/json

application/json

application/json

application/json

curl -X POST "https://example.com/user/update_banner" \  -H "Content-Type: application/json" \  -d '{    "banner": "iVBORw0KGgoAAAANSUhEUgAA..."  }'
{  "ok": true}
{  "error": "bad_request",  "message": "Missing or malformed parameter. Fix the request before retrying."}
{  "error": "unauthorized",  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."}
{  "error": "insufficient_credits",  "message": "Your balance is exhausted. Top up your credits to continue."}
{  "error": "forbidden",  "message": "The acting account is not authorized for this write action, or has no logged-in session."}
{  "error": "not_found",  "message": "The resource does not exist, for example a deleted tweet or a private account."}
{  "error": "rate_limited",  "message": "Too many requests. Back off and retry with exponential backoff."}
{  "error": "server_error",  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."}

Pricing

UnitPrice
Per call$0.0016
Per 1,000 calls$1.60

When to use

Use it to set your own account's header image, for example swapping a campaign banner your system already schedules. It only ever writes the account behind your session. To change the round profile picture instead, use user/update_avatar; to change name, bio, location or link, use user/update_profile.

Notes

  • banner is required. A request carrying none of banner, image or data is refused with 400 before anything is sent upstream, and is not billed.
  • An image X cannot decode is refused upstream with an error, not with ok: false. Verified against a deliberately malformed payload and against an empty one, both of which were refused.
  • Needs a session for the account you are acting as: either register one once (POST /customer/session), or pass per-call inline credentials as x-auth-token and x-ct0 request headers, which let a single API key act as many accounts. Returns 409 session_required if neither is supplied, 401 session_dead when the session has expired.
  • This takes effect immediately on x.com and there is NO UNDO. X keeps no history of a previous banner, so if you may want the old image back, fetch cover_picture from user/info and save the file before you call this. A successful write DROPS the cached user/info entry for the account, so the read-back below is immediately correct in the ordinary case. One honest limit: that cache lives in the process that served the write, so if your read lands on another instance you may see the previous value for up to two minutes. If a read-back looks unchanged, re-read after the window rather than concluding the write failed. Treating a stale read as a real absence is what destroyed a brand banner once already. Losing one this way is not hypothetical: it is why this note is here. A successful write DROPS the cached user/info entry for the account, so the read-back below is immediately correct in the ordinary case. One honest limit: that cache lives in the process that served the write, so if your read lands on another instance you may see the previous value for up to two minutes. If a read-back looks unchanged, re-read after the window rather than concluding the write failed. Treating a stale read as a real absence is what destroyed a brand banner once already.
  • READ THE BANNER BACK WITH user/info, not with anything else. At least one of X's own endpoints reports this field as empty for accounts that plainly have a banner, so a read that returns nothing is not evidence the account has none. user/info is GraphQL-backed and reports it as cover_picture. Allow for the cache window noted below before treating an unchanged value as a failed write.

FAQ

Can I pass a URL instead of base64?

No. The banner field holds base64-encoded image bytes in the JSON request body. There is no URL-fetch form and no multipart upload; encode the file before you send it.

How do I confirm the new banner actually applied?

Read the account back with user/info and check cover_picture. Use that field specifically: at least one of X's own endpoints reports it empty for accounts that plainly have a banner, so an empty answer from somewhere else does not mean the account has none. The write clears the cached entry, so the read is normally current; if it looks unchanged, re-read after about two minutes before concluding the write failed.

Can I restore my previous banner?

Only if you saved it yourself. X keeps no history, so once the new image is set the old URL stops resolving and the file is gone from our side and yours. Fetch cover_picture from user/info and download it before you call this if that matters.

What size should the image be?

X renders the header as a wide strip, so a 3:1 image is the shape that fills it without cropping; 1500x500 is a common choice and is what our own verification used. X rejects a payload it cannot decode with an error rather than accepting it silently.