Skip to content

Reporting

Report a post or a user account to X's moderation team. Both methods drive X's internal report-flow: they open a report, submit the reason you picked, and return the flow's completion state.

js
await client.report.user("1993037476219551744", "spam", { username: "Dear_Patriot" });
await client.report.tweet("1899999999999999999", "hate");

The same calls are also mirrored on the users and tweets namespaces, so you can report from wherever you already are:

js
await client.users.report("1993037476219551744", "spam");
await client.tweets.report("1899999999999999999", "hate");

report.user(userId, reason, opts?)

Report a user account.

js
const result = await client.report.user("1993037476219551744", "spam", {
  username: "Dear_Patriot",
});
console.log(result.status); // "success"
  • userId — the account's REST ID.
  • reason — a reason; an alias like "spam" or a raw option id like "SpamSimpleOption".
  • opts.username — optional screen name, used only to build the report's referer context. Cosmetic; the report works without it.

Alias: client.users.report(userId, reason, opts?).

report.tweet(tweetId, reason, opts?)

Report a post.

js
const result = await client.report.tweet("1899999999999999999", "violent_media");
console.log(result.status); // "success"
  • tweetId — the post's ID.
  • reason — a reason.

Alias: client.tweets.report(tweetId, reason, opts?).

Reasons

Pass either a short alias (case-insensitive, spaces or hyphens allowed) or the raw X option id. Any string ending in SimpleOption is sent through untouched, so new option ids keep working without a library update.

X categoryOption idAliases
Hate, Abuse, or HarassmentHateOrAbuseSimpleOptionhate, abuse, harassment
Violent SpeechViolentSpeechSimpleOptionviolent_speech
Child SafetyChildSafetySimpleOptionchild_safety
Private or Non-Consensual ContentPrivateContentSimpleOptionprivate, nonconsensual
Illegal and Regulated BehaviorsIRBSimpleOptionillegal, regulated
SpamSpamSimpleOptionspam
Suicide or Self-HarmSuicideSelfHarmSimpleOptionself_harm, suicide
Adult Sexual ContentAdultContentSimpleOptionadult, nsfw
Graphic or Violent MediaViolentMediaSimpleOptionviolent_media, graphic
ImpersonationImpersonationSimpleOptionimpersonation
Terrorism or Violent ExtremismTerrorismSimpleOptionterrorism, extremism

The alias map is exported if you want to build a picker:

js
import Emusks, { REPORT_REASONS } from "emusks";

Return value

Both methods return the raw completion state from X's report flow. A filed report looks like:

js
{
  flow_token: "eyJ...",
  status: "success",
  subtasks: [
    {
      subtask_id: "completion",
      progress_indication: { text: { text: "Submitted" }, percentage_complete: 100 },
      settings_list: {
        primary_text: { text: "Thanks for helping make X better for everyone" },
        // ...mute / block follow-up actions
      },
    },
    { subtask_id: "end-flow", end_flow: { status: "success", end_flow_type: "finish" } },
  ],
}

status: "success" and an end-flow subtask mean the report reached X's review queue. Some categories branch into a follow-up question instead of finishing immediately; in that case the returned subtasks describe the next step and the report is not yet filed.

Advanced

opts.variant merges into the request's context payload (client_location, client_referer, is_media, is_promoted, source, …) if you need to mimic a specific surface, and opts.startLocation overrides the flow's start location ("profile" for users, "home" for posts).

js
await client.report.tweet("1899999999999999999", "spam", {
  startLocation: "profile",
  variant: { client_location: "profile:tweet:", is_promoted: true },
});

not affiliated with X Corp.