Skip to main content
← Back to blog
by Engineering
tutorialbatchanalytics

Batch Operations: Analyze 100 Users in One Call

Why Batch Operations?

When building analytics dashboards or monitoring multiple accounts, making individual API calls for each user is slow and wasteful. XCROP's batch endpoints let you look up 100 users or 100 tweets in a single request — dramatically reducing latency and simplifying your code.

Batch User Lookup

Basic Request

PYTHON
import requests
import os

response = requests.post(
    "https://xcrop.io/api/v2/users/batch",
    headers={
        "Authorization": "Bearer " + os.environ["XCROP_API_KEY"],
        "Content-Type": "application/json"
    },
    json={
        "usernames": [
            "VitalikButerin",
            "caboronft",
            "CryptoHayes",
            "DefiIgnas",
            "Pentosh1"
        ]
    }
)

users = response.json()["data"]
for user in users:
    print("@" + user["username"])
    print("  Followers: " + str(user["followers"]))
    print("  Following: " + str(user["following"]))
    print("  Tweets: " + str(user["tweets_count"]))
    print()

Response Format

Each user in the batch response follows the standard user object:

JSON
{
  "data": [
    {
      "id": "123456789",
      "username": "VitalikButerin",
      "name": "vitalik.eth",
      "description": "Ethereum co-founder...",
      "followers": 5400000,
      "following": 800,
      "tweets_count": 12000,
      "listed": 45000,
      "verified": false,
      "profile_image": "https://pbs.twimg.com/...",
      "created_at": "Mon Jun 15 18:01:37 +0000 2013"
    }
  ],
  "meta": {
    "total": 5,
    "latency_ms": 320
  }
}

Limits

Maximum 100 usernames per batch request
Costs 18 credits per user returned
For larger sets, split into multiple batch calls

Batch Tweet Lookup

Similarly, look up multiple tweets by ID in one call:

JAVASCRIPT
const response = await fetch("https://xcrop.io/api/v2/tweets/batch", {
  method: "POST",
  headers: {
    "Authorization": "Bearer " + apiKey,
    "Content-Type": "application/json"
  },
  body: JSON.stringify({
    ids: [
      "1234567890123456789",
      "9876543210987654321",
      "5555555555555555555"
    ]
  })
});

const { data: tweets } = await response.json();
tweets.forEach(tweet => {
  console.log("@" + tweet.author.username + ": " + tweet.text.slice(0, 80));
  console.log("  Likes: " + tweet.metrics.likes + " | RT: " + tweet.metrics.retweets);
});
Maximum 100 tweet IDs per batch request
Costs 15 credits per tweet returned

Building a KOL Analytics Dashboard

Here's a complete example that fetches multiple KOL profiles, compares their metrics, and ranks them:

PYTHON
import requests
import os

API_KEY = os.environ["XCROP_API_KEY"]
HEADERS = {
    "Authorization": "Bearer " + API_KEY,
    "Content-Type": "application/json"
}
BASE_URL = "https://xcrop.io/api/v2"

# Define KOLs to track
KOLS = [
    "VitalikButerin", "CryptoHayes", "DefiIgnas",
    "Pentosh1", "inversebrah", "MustStopMurad",
    "colocobot", "blknoiz06", "GiganticRebirth",
    "EmberCN"
]

def fetch_kol_profiles(usernames):
    """Batch fetch KOL profiles."""
    response = requests.post(
        BASE_URL + "/users/batch",
        headers=HEADERS,
        json={"usernames": usernames}
    )
    return response.json()["data"]

def get_recent_tweets(username, count=20):
    """Fetch recent tweets for engagement analysis."""
    response = requests.get(
        BASE_URL + "/users/" + username + "/tweets",
        headers=HEADERS,
        params={"count": count, "sort": "latest"}
    )
    return response.json()["data"]

def calculate_engagement_rate(tweets, followers):
    """Calculate average engagement rate from recent tweets."""
    if not tweets or followers == 0:
        return 0

    total_engagement = 0
    for tweet in tweets:
        m = tweet["metrics"]
        total_engagement += m["likes"] + m["retweets"] + m["replies"]

    avg_engagement = total_engagement / len(tweets)
    return round(avg_engagement / followers * 100, 4)

# Step 1: Batch fetch all KOL profiles
print("Fetching " + str(len(KOLS)) + " KOL profiles...")
profiles = fetch_kol_profiles(KOLS)

# Step 2: Calculate engagement rates
results = []
for profile in profiles:
    username = profile["username"]
    tweets = get_recent_tweets(username, count=10)
    eng_rate = calculate_engagement_rate(tweets, profile["followers"])

    results.append({
        "username": username,
        "followers": profile["followers"],
        "tweets_count": profile["tweets_count"],
        "engagement_rate": eng_rate
    })

# Step 3: Rank by engagement rate
results.sort(key=lambda x: x["engagement_rate"], reverse=True)

print("\n=== KOL Rankings by Engagement Rate ===")
for i, kol in enumerate(results):
    rank = str(i + 1)
    print(rank + ". @" + kol["username"])
    followers_k = str(round(kol["followers"] / 1000))
    print("   Followers: " + followers_k + "K")
    print("   Engagement rate: " + str(kol["engagement_rate"]) + "%")
    print()

Tracking Follower Growth Over Time

Combine batch lookups with periodic polling to track follower changes:

PYTHON
import requests
import time
import json
import os

API_KEY = os.environ["XCROP_API_KEY"]
HEADERS = {
    "Authorization": "Bearer " + API_KEY,
    "Content-Type": "application/json"
}
BASE_URL = "https://xcrop.io/api/v2"

TRACKED_USERS = ["VitalikButerin", "CryptoHayes", "DefiIgnas"]
HISTORY_FILE = "follower_history.json"

def load_history():
    try:
        with open(HISTORY_FILE, "r") as f:
            return json.load(f)
    except FileNotFoundError:
        return {}

def save_history(history):
    with open(HISTORY_FILE, "w") as f:
        json.dump(history, f, indent=2)

def snapshot_followers():
    """Take a snapshot of follower counts."""
    response = requests.post(
        BASE_URL + "/users/batch",
        headers=HEADERS,
        json={"usernames": TRACKED_USERS}
    )

    if response.status_code != 200:
        print("Error: " + str(response.status_code))
        return

    users = response.json()["data"]
    history = load_history()
    timestamp = time.strftime("%Y-%m-%d %H:%M")

    for user in users:
        username = user["username"]
        followers = user["followers"]

        if username not in history:
            history[username] = []

        prev = history[username][-1]["followers"] if history[username] else followers
        change = followers - prev

        history[username].append({
            "timestamp": timestamp,
            "followers": followers,
            "change": change
        })

        sign = "+" if change >= 0 else ""
        print("@" + username + ": " + str(followers) + " (" + sign + str(change) + ")")

    save_history(history)

# Run snapshot every hour
print("Tracking follower growth...")
while True:
    snapshot_followers()
    time.sleep(3600)  # Check every hour

Comparing Users with Search

Find and compare users matching specific criteria using the user search endpoint:

PYTHON
# Search for DeFi-focused accounts
response = requests.post(
    BASE_URL + "/search/users",
    headers=HEADERS,
    json={
        "query": "DeFi analyst",
        "count": 20,
        "sort": "followers"
    }
)

users = response.json()["data"]
print("Top DeFi analysts by followers:")
for user in users[:10]:
    followers_k = str(round(user["followers"] / 1000))
    print("  @" + user["username"] + " — " + followers_k + "K followers")

Best Practices

1. Batch whenever possible — 1 batch call for 100 users beats 100 individual calls
2. Cache profiles — User profiles are cached for 5 minutes; don't re-fetch more often
3. Use sort parameters — Sort followers by followers count to find the most influential ones first
4. Combine batch + timeline — Fetch profiles in batch, then get tweets for top accounts only
5. Mind the credits — Batch user lookup costs 18 credits/user; 100 users = 1,800 credits per call

Credit Usage

Batch user lookup: 18 credits per user (max 100 per call)
Batch tweet lookup: 15 credits per tweet (max 100 per call)
User tweets: 15 credits per tweet returned
User search: 18 credits per user returned
100-user batch = 1,800 credits — with Pro plan ($9.9/mo, 2M credits) you can do ~1,100 batch calls/month