> ## Documentation Index
> Fetch the complete documentation index at: https://docs.xquik.com/llms.txt
> Use this file to discover all available pages before exploring further.

# X community members & profile export API guide

> Scrape X community members into profile rows with usernames, bios, verification, and follower counts. Export every cursor page for review or CRM imports.

<Panel>
  <Tabs defaultTabIndex={0} sync={false}>
    <Tab title="200" id="response-x-community-members-200">
      ```json theme={null}
      {
        "users": [],
        "has_next_page": false,
        "next_cursor": ""
      }
      ```
    </Tab>

    <Tab title="400" id="response-x-community-members-400">
      ```json theme={null}
      {
        "error": "invalid_input",
        "message": "Invalid input. Check the request body."
      }
      ```
    </Tab>

    <Tab title="401" id="response-x-community-members-401">
      ```json theme={null}
      {
        "error": "unauthenticated",
        "message": "Authentication required."
      }
      ```
    </Tab>

    <Tab title="402" id="response-x-community-members-402">
      ```json theme={null}
      {
        "error": "insufficient_credits",
        "message": "Insufficient credits. Top up or subscribe to continue."
      }
      ```
    </Tab>

    <Tab title="404" id="response-x-community-members-404">
      ```json theme={null}
      {
        "error": "not_found",
        "message": "Resource not found."
      }
      ```
    </Tab>

    <Tab title="424" id="response-x-community-members-424">
      ```json theme={null}
      {
        "error": "x_api_unavailable",
        "message": "X data source temporarily unavailable. Try again later."
      }
      ```
    </Tab>

    <Tab title="429" id="response-x-community-members-429">
      ```json theme={null}
      {
        "error": "rate_limit_exceeded",
        "message": "Too many requests. Try again later.",
        "retryAfter": 60
      }
      ```
    </Tab>

    <Tab title="502" id="response-x-community-members-502">
      ```json theme={null}
      {
        "error": "x_api_unavailable",
        "message": "X data source temporarily unavailable. Try again later."
      }
      ```
    </Tab>

    <Tab title="503" id="response-x-community-members-503">
      ```json theme={null}
      {
        "error": "x_api_unavailable",
        "message": "Xquik is busy right now. Retry shortly."
      }
      ```
    </Tab>
  </Tabs>
</Panel>

<blockquote className="agent-llms-directive">
  For the complete documentation index, see <a href="/llms.txt">llms.txt</a>.
</blockquote>

Scrape X community members into profile rows. Store the community and user IDs with every cursor result. Keep the username, bio, verification, follower count, and cursor.

## X community member scraping questions

### Scrape X community members

Call `GET /api/v1/x/communities/{id}/members` with the numeric community ID.
Store the community ID and stable user ID. Keep the username, profile name,
bio, location, and verification. Record an ISO 8601 collection time before
requesting another cursor. Store available follower and following counts.
Keep the profile image URL. Store the cursor returned with each profile batch.

Save the page before advancing its opaque cursor. Use `has_next_page` as the
only pagination guard. Send another request only for the boolean `true`. Reuse
the exact `next_cursor`. Deduplicate a resumed page by community ID and user ID.
Mark credit-bounded, failed, or interrupted runs as partial. Use the moderators
route for role-specific profiles. The members route returns every visible
member profile.

### What is the best way to extract data from a Twitter community?

First decide which community records the workflow needs. Use the info
route for the community name and description. Use the members route for user
IDs and profile fields. Use the moderators route for role-specific profiles.
Retrieve recent Community posts through the tweets route. Search Community
posts for a keyword through Community Search.

Keep community profiles and tweets in separate tables. Join them with stable
community and user IDs. Save page cursors, collection times, row counts, and
completion states. Export JSON for applications. Create CSV or XLSX only when
analysts need rows. Do not merge membership, moderator roles, and tweet
activity into one record.

### How do I scrape members from an X community?

Call `GET /api/v1/x/communities/{id}/members` with the numeric community ID.
Store each user ID, username, profile name, bio, and verification state. Add
the follower count and page cursor.

Stop when `has_next_page` is false. Until then, send `next_cursor` without
modification. Save each profile page before advancing its cursor.

Deduplicate resumed pages by stable user ID. Write the community ID into every
exported profile record. Record the collection time because usernames, bios,
verification, and audience counts can change. Do not infer moderator status
from membership.
Use the dedicated moderators route for that role. Mark an interrupted or
credit-bounded export as partial.

### Twitter community API

Choose the route that matches the record. The info route returns community
details. The members route returns member profiles. The moderators route
returns moderator profiles. The tweets route returns recent community posts.
Community search returns posts matching a query.

For member exports, build one roster row per community ID and user ID. Keep
profile fields, source cursor, collection time, and completion state. For tweet
exports, store Tweet ID, author ID, text, timestamp, engagement, media, and
cursor. Keep those schemas separate. Use stable IDs for joins. Respect API-key
scope, credits, page limits, and rate limits.

### How should I compare community member lists?

Complete every cursor page before comparing snapshots. Mark interrupted runs
as partial. Use community ID plus user ID as the comparison key.

Report newly observed and missing members separately. Never assign a reason
for an addition or removal. Refresh a profile only when later work requires
current follower counts, following counts, or biographies.

<Note>
  Requested result counts are upper bounds for paid authenticated calls. Low
  credit balances can reduce a page or ID list. If zero results are affordable,
  Xquik returns `402 insufficient_credits`.
</Note>

<Callout icon="coins" color="#5c3327">
  **1 credit per result returned** · [All plans](https://xquik.com/#pricing) from \$0.00012/credit
</Callout>

<CodeGroup>
  ```bash cURL theme={null}
  curl https://xquik.com/api/v1/x/communities/1234567890/members \
    -H "x-api-key: xq_your_api_key_here" | jq
  ```

  ```javascript Node.js theme={null}
  const communityId = "1234567890";
  const response = await fetch(`https://xquik.com/api/v1/x/communities/${communityId}/members`, {
    headers: { "x-api-key": "xq_your_api_key_here" },
  });
  const data = await response.json();
  const nextCursor = data.has_next_page ? data.next_cursor : null;
  const memberRows = data.users.map((user) => ({
    community_id: communityId,
    member_id: user.id,
    username: user.username,
    display_name: user.name,
    bio: user.description ?? null,
    follower_count: user.followers ?? null,
    verified: user.verified ?? false,
    profile_image_url: user.profilePicture ?? null,
    next_cursor: nextCursor,
  }));

  process.stdout.write(JSON.stringify(memberRows, null, 2));
  ```

  ```python Python theme={null}
  import json
  import requests

  community_id = "1234567890"
  response = requests.get(
      f"https://xquik.com/api/v1/x/communities/{community_id}/members",
      headers={"x-api-key": "xq_your_api_key_here"},
  )
  data = response.json()
  next_cursor = data["next_cursor"] if data["has_next_page"] else None
  member_rows = [
      {
          "community_id": community_id,
          "member_id": user["id"],
          "username": user["username"],
          "display_name": user["name"],
          "bio": user.get("description"),
          "follower_count": user.get("followers"),
          "verified": user.get("verified", False),
          "profile_image_url": user.get("profilePicture"),
          "next_cursor": next_cursor,
      }
      for user in data["users"]
  ]

  print(json.dumps(member_rows, indent=2))
  ```
</CodeGroup>

Use `GET /x/communities/{id}/members` for member exports, CRM enrichment,
audience review, or moderator handoff. It creates one row per community member.
Store `community_id`, `member_id`, `username`, `display_name`, `bio`,
`follower_count`, `verified`, `profile_image_url`, and `next_cursor`.

## Build a community member export

The community member export becomes complete after every cursor page finishes.
Save each profile page before advancing its cursor. Mark credit-bounded,
failed, and interrupted runs as partial membership snapshots. Mark the export
complete only after `has_next_page` is `false`.

A member row shows that the account belongs to the community. It does not prove posting
activity. Retrieve recent Community posts through
[Community Tweets](/api-reference/x/community-tweets). Use
[Community Search](/api-reference/x/community-search) to find posts by keyword.
Join those posts to member profiles by `manifest_id`, `community_id`, and stable
user ID.

Use [Community Moderators](/api-reference/x/community-moderators) for
role-specific profiles. Verification and follower counts do not prove a
moderator role.

X Lists use different IDs and membership rules. Review X's official
[List Members Lookup](https://docs.x.com/x-api/lists/list-members/quickstart/list-members-lookup)
before migrating a List workflow. Store `source_type` and its source ID. Use
`community_id` for Community rows and `list_id` for List rows. Join and
deduplicate with the source ID plus `member_id`.

Use this route to enumerate profiles that belong to one community. Keep the
community ID on every exported row. A username alone cannot identify its
source community.

Choose columns that support the next task:

* User ID, username, and profile name.
* Biography, location, and verification state.
* Follower and following counts.
* Store the Community ID and cursor with every page's ISO 8601 collection time.

Use this Community member roster for directories, CRM enrichment, or moderator
review.
Do not label every member as a moderator. Use the moderators route to retrieve
only moderator profiles.

Use `has_next_page` as the only pagination check. The next request requires
the boolean value `true`. Pass `next_cursor` without modification. Store each
page before saving its cursor. Deduplicate repeated results by user ID after
resuming a job.

Profile fields can change after collection. Record an ISO 8601 time for every
returned profile. Refresh the profile through user lookup when the workflow requires
current bios, follower counts, following counts, or avatars.

## Compare community membership snapshots

Collect every cursor page before comparing membership. Mark interrupted runs
as partial.

Use community ID and user ID as the comparison key. Record newly observed and
missing members separately. Avoid inferring why a membership changed.

Keep the snapshot's page count, row count, first cursor, and completion time.
With these values, reviewers can tell a real change from an incomplete
export.

Store membership notes outside returned profile fields. Never place private
moderation notes inside a public username or biography column.

When another process adds moderator status, store it in a separate
`community_role` column.

## Path parameters

<ParamField path="id" type="string" required>
  Community ID (numeric string).
</ParamField>

## Query parameters

<ParamField query="cursor" type="string">
  Pagination cursor from a previous response. Omit for the initial request.
</ParamField>

<ParamField query="pageSize" type="number">
  Results per request. Range: 20-200. Default: `20`.
</ParamField>

### User result filters

These filters apply before billing. Selective filters can return fewer rows.

<ParamField query="minFollowers" type="integer">
  Require this minimum follower count. Filtering happens before billing.
</ParamField>

<ParamField query="maxFollowers" type="integer">
  Allow this maximum follower count. Missing counts pass this filter.
</ParamField>

<ParamField query="minFollowing" type="integer">
  Require this minimum following count.
</ParamField>

<ParamField query="maxFollowing" type="integer">
  Allow this maximum following count. Missing counts pass this filter.
</ParamField>

<ParamField query="minStatuses" type="integer">
  Require this minimum post count.
</ParamField>

<ParamField query="maxStatuses" type="integer">
  Allow this maximum post count. Missing counts pass this filter.
</ParamField>

<ParamField query="minAccountAgeDays" type="integer">
  Require this minimum account age in days.
</ParamField>

<ParamField query="verifiedOnly" type="boolean">
  When `true`, only return verified profiles.
</ParamField>

<ParamField query="verifiedType" type="string">
  Match the exact verification type.
</ParamField>

<ParamField query="hasWebsite" type="boolean">
  When `true`, require a profile website.
</ParamField>

<ParamField query="hasLocation" type="boolean">
  When `true`, require a profile location.
</ParamField>

<ParamField query="bioContains" type="string">
  Require every comma-separated or line-separated bio term.
</ParamField>

<ParamField query="locationContains" type="string">
  Require this text in the profile location.
</ParamField>

<ParamField query="usernameContains" type="string">
  Require this text in the username.
</ParamField>

## Headers

<ParamField header="x-api-key" type="string">
  Full account key. Sessions and OAuth also work.
</ParamField>

<ParamField header="Authorization" type="string">
  `Bearer xq_your_guest_key_here` for `paid_reads`.
</ParamField>

## Response

### 200 OK

<ResponseField name="users" type="object[]">
  Array of community members.
  **User object fields.**

  <ResponseField name="id" type="string">
    User ID.
  </ResponseField>

  <ResponseField name="username" type="string">
    X username.
  </ResponseField>

  <ResponseField name="name" type="string">
    Display name.
  </ResponseField>

  <ResponseField name="description" type="string">
    Profile bio.
  </ResponseField>

  <ResponseField name="followers" type="number">
    Reports the profile's follower count.
  </ResponseField>

  <ResponseField name="following" type="number">
    Following count.
  </ResponseField>

  <ResponseField name="verified" type="boolean">
    Verified status.
  </ResponseField>

  <ResponseField name="profilePicture" type="string">
    Profile image URL.
  </ResponseField>

  <ResponseField name="location" type="string">
    Profile location.
  </ResponseField>

  <ResponseField name="createdAt" type="string">
    Account creation date (ISO 8601).
  </ResponseField>

  <ResponseField name="statusesCount" type="number">
    Total number of tweets posted. Omitted if unavailable.
  </ResponseField>

  <ResponseField name="coverPicture" type="string">
    Cover or banner image URL. Omitted if unavailable.
  </ResponseField>

  <ResponseField name="mediaCount" type="number">
    Total number of media tweets posted. Omitted if unavailable.
  </ResponseField>

  <ResponseField name="url" type="string">
    Website URL from profile. Omitted if empty.
  </ResponseField>

  <ResponseField name="favouritesCount" type="number">
    Total number of tweets liked. Omitted if unavailable.
  </ResponseField>

  <ResponseField name="hasCustomTimelines" type="boolean">
    Whether the user has custom timelines. Omitted if unavailable.
  </ResponseField>

  <ResponseField name="isTranslator" type="boolean">
    Whether the user is an X translator. Omitted if unavailable.
  </ResponseField>

  <ResponseField name="withheldInCountries" type="string[]">
    Country codes where the account is withheld. Omitted if empty.
  </ResponseField>

  <ResponseField name="possiblySensitive" type="boolean">
    Whether X flags the account as possibly sensitive. Omitted if unavailable.
  </ResponseField>

  <ResponseField name="pinnedTweetIds" type="string[]">
    Lists pinned Tweet IDs. Omitted if none.
  </ResponseField>

  <ResponseField name="isAutomated" type="boolean">
    Whether X marks the account as automated. Omitted if unavailable.
  </ResponseField>

  <ResponseField name="automatedBy" type="string">
    Username of the account operator if automated. Omitted if not automated.
  </ResponseField>

  <ResponseField name="unavailable" type="boolean">
    Whether the account is unavailable. Omitted if available.
  </ResponseField>

  <ResponseField name="unavailableReason" type="string">
    Reason the account is unavailable. Omitted if available.
  </ResponseField>

  <ResponseField name="verifiedType" type="string">
    Verification type (for example `Business`, `Government`). Omitted if not verified or standard blue
    check.
  </ResponseField>

  <ResponseField name="profile_bio" type="object">
    Structured profile bio with entity annotations. Omitted if unavailable.
  </ResponseField>

  <ResponseField name="isBlueVerified" type="boolean">
    Whether the account has X Premium verification. Omitted if unavailable.
  </ResponseField>

  <ResponseField name="isVerified" type="boolean">
    Normalized verification status. Omitted if unavailable.
  </ResponseField>

  <ResponseField name="profileBannerUrl" type="string">
    Profile banner URL. Omitted if unavailable.
  </ResponseField>

  <ResponseField name="protected" type="boolean">
    Indicates whether the account protects its Tweets. Omitted if unavailable.
  </ResponseField>

  <ResponseField name="communityRole" type="string">
    Role within the requested community context. Omitted outside community results.
  </ResponseField>
</ResponseField>

<ResponseField name="has_next_page" type="boolean">Whether more results are available.</ResponseField>
<ResponseField name="next_cursor" type="string">Cursor for the next results. Pass as the `cursor` query parameter.</ResponseField>

```json theme={null}
{
  "users": [
    {
      "id": "987654321",
      "username": "username",
      "name": "Xquik",
      "followers": 10000,
      "verified": true,
      "profilePicture": "https://pbs.twimg.com/profile_images/xquik/photo.jpg"
    }
  ],
  "has_next_page": true,
  "next_cursor": "DAACCgACGE..."
}
```

### 400 Invalid community ID

```json theme={null}
{ "error": "invalid_community_id" }
```

The community ID is empty or invalid.

### 401 Unauthenticated

Anonymous requests get `WWW-Authenticate: Bearer` and a guest wallet checkout action. This is not a Payment challenge.

```json theme={null}
{ "error": "unauthenticated" }
```

Missing or invalid API key.

### 402 Payment required

Account keys get account options. Guest keys get guest top-up only.
No checkout starts automatically. Confirm any payment action.

### 404 Community not found

```json theme={null}
{ "error": "not_found" }
```

Xquik could not resolve the community. Check the community ID.

### 502 X API unavailable

```json theme={null}
{ "error": "x_api_unavailable" }
```

The read service returned an error. Retry after a short delay.

### 429 Rate limit exceeded

```json theme={null}
{ "error": "rate_limit_exceeded", "retryAfter": 60 }
```

You exceeded your tier rate limit. Wait for the `Retry-After` header before retrying.

### 424 Dependency failed

```json theme={null}
{ "error": "x_api_unavailable" }
```

Send `xquik-api-contract: 2026-04-29` to opt in to HTTP 424. Default v1 returns
HTTP 502 with `x_api_unavailable`.

<Note>
  **Next steps.** [Community Info](/api-reference/x/community-info) for community details, or [Community Moderators](/api-reference/x/community-moderators) to list moderators.
</Note>

<div className="related-api-links">
  <Accordion title="Related follower, list & community APIs" icon="link">
    * Profiles: [Search users](/api-reference/x/search-users) · [Search autocomplete](/api-reference/x/search-autocomplete) · [Get user](/api-reference/x/twitter-profile-lookup) · [Batch users](/api-reference/x/batch-users)
    * Followers: [Followers](/api-reference/x/followers) · [Following](/api-reference/x/following) · [Follower IDs](/api-reference/x/follower-ids) · [Following IDs](/api-reference/x/following-ids) · [Creator subscriptions](/api-reference/x/user-subscriptions) · [Affiliates](/api-reference/x/user-affiliates) · [Similar accounts](/api-reference/x/user-similar) · [Verified followers](/api-reference/x/verified-followers) · [Followers you know](/api-reference/x/followers-you-know) · [Check follower](/api-reference/x/check-follower)
    * Lists: [Search lists](/api-reference/x/search-lists) · [User lists](/api-reference/x/user-lists) · [List memberships](/api-reference/x/user-list-memberships) · [List members](/api-reference/x/list-members) · [List followers](/api-reference/x/list-followers)
    * Communities: [Find](/api-reference/x/community-find) · [Popular](/api-reference/x/community-popular) · [Topics](/api-reference/x/community-topics) · [Suggested](/api-reference/x/community-suggested) · [Details](/api-reference/x/community-info) · [Members](/api-reference/x/community-members) · [Moderators](/api-reference/x/community-moderators) · [Timeline](/api-reference/x/community-tweets) · [Media](/api-reference/x/community-media) · [Keyword search](/api-reference/x/community-search)
  </Accordion>
</div>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.