---
title: "Update an article"
method: POST
path: "/client/articles/update"
tags: ["Account actions"]
---

# Update an article

`POST /client/articles/update`

## Request

- Base URL: `https://api.twittrapi.com`
- URL: `https://api.twittrapi.com/client/articles/update`
- Auth: API key in header `X-API-KEY`

Change the title, content or cover of an article. Fields you leave out stay as they are.

Send at least one of title, text, content_state, cover_media_id or remove_cover. text and content_state replace the whole content. Title, content and cover are saved one after the other, like on x.com; when one fails, its answer is returned and the rest is skipped. Billed as one call.

Needs X Premium on the account. Without it X refuses with error code 37 ("Twitter Blue claim is not enabled").

No simple format: with format=simple the answer is the usual {status_code, response} wrapper.

Reference: https://www.twittrapi.com/docs/account-actions/client-articles-update

## Request body

- object
  - `cookie` string, required: Cookie header of your own logged-in X session: auth_token=...; ct0=... (guest_id is used when present). How to copy it: /docs/x-session.
  - `proxy` string, required: Your proxy, format http://user:pass@host:port. The requests to X go out through it. Used only for this request.
  - `article_id` string, required: Numeric ID of the article, from /client/articles.
  - `title` string: Title of the article.
  - `text` string: Content as plain text, one paragraph per line. Send text or content_state, not both.
  - `content_state` string: Content in the format of the x.com editor, {"blocks": [...], "entity_map": [...]}, as /client/articles/get returns it. Use it for headings, links and styles.
  - `cover_media_id` string: Numeric media ID from /client/media or /client/media/video to use as the cover.
  - `cover_media_category` string: Type of the cover: DraftTweetImage, DraftTweetGif or AmplifyVideo (video).
  - `remove_cover` boolean: true removes the cover. Not together with cover_media_id.

## Response `200`

Wrapper built by the API: {"status_code": <X status>, "response": "<X response body as a string>"}. The HTTP status is X's status when X answered 4xx or 5xx, otherwise 200. Parse response a second time to get X's JSON.

- RawPassthrough: X's own JSON (raw format, the default), passed through unchanged. The shape is X's and can change; see https://www.twittrapi.com/docs/response-format.

## Other responses

- `400`: The body is not valid JSON.
- `401`: Missing or unknown API key. Not charged.
- `402`: No balance left, or the trial expired. Not charged. Top up in the dashboard.
- `403`: Key deactivated, or the endpoint is not in your plan (trial keys and account actions). Not charged.
- `407`: The proxy is unreachable or timed out.
- `422`: A required field is missing (including proxy), an ID is not numeric, or the cookie has no ct0. Also: the account is suspended, X rejected the session, or the text was already posted. None of the fields to change is set, title or text is not a string, content_state is not an object with blocks and entity_map, or both text and content_state are sent, cover_media_id is not numeric, cover_media_category has another value, remove_cover is not true or false, or remove_cover is sent with cover_media_id.
- `429`: Rate limit for your key exceeded. Not charged. No Retry-After header: back off exponentially.
- `500`: Something failed on our side or between us and X. Refunded (400, 407, 408, 409 or a 5xx error are refunded). Retry with backoff.
- `default`: Any status X answers with (for example 401, 403, 404): passed through with X's body.

---

[API](https://skmtc.dev/twittrapi/apis/twittrapi-api.md) · [All operations](https://skmtc.dev/twittrapi/apis/twittrapi-api/llms.txt) · [OpenAPI document](https://skmtc.dev/twittrapi/apis/twittrapi-api/revisions/0618e38b54c2?raw)
