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.
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:
await client.users.report("1993037476219551744", "spam");
await client.tweets.report("1899999999999999999", "hate");report.user(userId, reason, opts?)
Report a user account.
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.
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 category | Option id | Aliases |
|---|---|---|
| Hate, Abuse, or Harassment | HateOrAbuseSimpleOption | hate, abuse, harassment |
| Violent Speech | ViolentSpeechSimpleOption | violent_speech |
| Child Safety | ChildSafetySimpleOption | child_safety |
| Private or Non-Consensual Content | PrivateContentSimpleOption | private, nonconsensual |
| Illegal and Regulated Behaviors | IRBSimpleOption | illegal, regulated |
| Spam | SpamSimpleOption | spam |
| Suicide or Self-Harm | SuicideSelfHarmSimpleOption | self_harm, suicide |
| Adult Sexual Content | AdultContentSimpleOption | adult, nsfw |
| Graphic or Violent Media | ViolentMediaSimpleOption | violent_media, graphic |
| Impersonation | ImpersonationSimpleOption | impersonation |
| Terrorism or Violent Extremism | TerrorismSimpleOption | terrorism, extremism |
The alias map is exported if you want to build a picker:
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:
{
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).
await client.report.tweet("1899999999999999999", "spam", {
startLocation: "profile",
variant: { client_location: "profile:tweet:", is_promoted: true },
});