# Threads Followers & Following Scraper | No Login (`scraping_solutions/threads-followers-following-scraper`) Actor

Download available followers or following from public Threads accounts. Get profile links, follower counts when available, deduplication and JSON, CSV or Excel exports for audience research. No Threads login, cookies or additional API key required.

- **URL**: https://apify.com/scraping\_solutions/threads-followers-following-scraper.md
- **Developed by:** [Scraping Solutions](https://apify.com/scraping_solutions) (community)
- **Categories:** Social media, Lead generation
- **Stats:** 8 total users, 7 monthly users, 89.2% runs succeeded, 0 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

from $0.85 / 1,000 results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Threads Followers & Following Scraper

By **scraping\_solutions**. Extract public Threads follower or following profiles, with validated inputs, deduplication, incremental results, budget protection and resumable progress.

**No Threads login, cookies, additional API key or separate service subscription is required.** Enter the accounts you want to analyze and run the Actor on Apify.

### Quick start

```json
{
  "usernames": ["neeturaj2525"],
  "type": "followers",
  "maxResultsPerUser": 20
}
```

1. Enter public usernames, `@usernames`, or Threads profile URLs.
2. Choose followers or following. Each run extracts one relationship.
3. Set a result maximum and, on Apify, the maximum run charge and timeout.
4. Run and inspect the dataset and the key-value store's `OUTPUT` record. Export results through Apify as JSON, CSV or Excel.

The result maximum is not a guarantee of availability. A response without a pagination cursor ends that relation even when fewer results are available than requested.

### Input

| Field | Type | Default | Meaning |
| --- | --- | --- | --- |
| `usernames` | String array | Required | Public Threads usernames or profile URLs; duplicate sources are processed once. |
| `type` | String | `followers` | `followers` or `following`. One relationship per run. |
| `maxResultsPerUser` | Integer, minimum 0 | 100 | Maximum saved profiles per source account for the selected relationship. `0` means all accessible, subject to quota and budget. |

Whitespace at the ends and a leading `@` are removed. Profile URLs on `threads.com` or `threads.net` are normalized to lowercase usernames. Internal spaces, emails, empty names, invalid characters and non-profile URLs are rejected before provider calls. Valid entries in a mixed list continue; rejected entry indexes and reasons appear in warnings and `OUTPUT.rejectedInputs`. If none are valid, the run reports `INVALID_INPUT`, exits nonzero and makes no provider requests.

Usernames accept 1-30 ASCII letters, numbers, underscores or dots; the first character cannot be a dot. Unsupported objects and non-string array entries are rejected. Limits must be integers, not strings, booleans or decimal values.

**One relationship per run.** A limit of 100 means up to 100 followers OR up to 100 following per account. To extract the other relationship, start a separate run with fresh storage. Old inputs containing `type: "both"` or `maxRequests` are rejected before provider calls; select a supported type and remove the obsolete field.

### Free plan limits

The following limits apply to Apify Free accounts. They do not apply to paid Apify accounts.

| Apify Free execution channel | Accounts per run | Per-run configured cap | Daily reserved-result cap | Runs per UTC day |
| --- | ---: | ---: | ---: | ---: |
| API / MCP / automation | First valid account only | 1,300 | 1,000 | 5 |
| Apify Console / Web | First valid account only | 1,750 | 1,750 | 15 |

The smaller remaining allowance wins: API/MCP can never actually deliver more than **1,000 per day**, despite the 1,300 per-run setting. A result limit of `0` does not bypass Free limits. Paid Apify accounts have no additional Free-plan cap.

API, MCP, CLI, Actor calls, scheduled jobs, webhooks and unknown origins share the API bucket. Web has its own bucket. One quota reservation is reused when the same run resumes. Different runs may use different source accounts, but share the same customer/day/channel allowance.

Quota is **reserved before extraction** and is not refunded after failures, early ends or cancellations. Reservations are NOT charges: only saved unique result rows generate result events. An Apify Free account does not mean that using the Actor is free of charge.

Daily exhaustion reports `FREE_API_DAILY_LIMIT_REACHED` or `FREE_WEB_DAILY_LIMIT_REACHED` before extraction. If your Apify plan or remaining allowance cannot be verified, the run stops without fetching profiles rather than silently bypassing the limit.

### Output fields

One dataset row is one found profile. Audit records and summaries are never mixed into customer results.

| Field | Meaning |
| --- | --- |
| `sourceUsername` | Normalized source account. |
| `relation` | `follower` or `following`. |
| `userId` | Profile identifier, preserved as a string. |
| `username` | Returned username, when supplied. |
| `profileUrl` | Threads profile link derived from a valid returned username: `https://www.threads.com/@username`. |
| `fullName` | Display name, when available. |
| `followersCount` | Follower count of the found profile, when available as a non-negative integer. A real zero is preserved. |
| `profilePicUrl` | Profile picture URL, when available. |
| `isVerified` | Verification status, when available as a boolean. |
| `isPrivate` | Privacy status of the found profile, when available as a boolean. |
| `scrapedAt` | Extraction time in UTC, ISO 8601. |

Missing values are omitted, not fabricated. Records without a usable ID are skipped; if an entire non-empty response lacks IDs, it is a provider-format error.

`followersCount` describes each downloaded profile, not the source account or the number of rows extracted. A missing or invalid count is omitted, never replaced with zero. `profileUrl` is omitted if no valid username is available. These fields use the existing page response, with no extra requests or enrichment charge. Existing dataset rows are not retroactively updated.

Illustrative output with synthetic values:

```json
{
  "sourceUsername": "neeturaj2525",
  "relation": "follower",
  "userId": "1234567890",
  "username": "example_profile",
  "profileUrl": "https://www.threads.com/@example_profile",
  "fullName": "Example Profile",
  "followersCount": 1250,
  "profilePicUrl": "https://example.com/avatar.jpg",
  "isVerified": false,
  "isPrivate": false,
  "scrapedAt": "2026-09-27T09:00:00Z"
}
```

### Pricing: result-only pay-per-event

Prices verified on September 28, 2026, against the active Apify monetization configuration effective September 27, 2026, at 23:40 UTC. See the Actor's [Pricing tab](https://apify.com/scraping_solutions/threads-followers-following-scraper/pricing) for the current price applicable to your Apify account. All prices are in USD.

| Customer plan | Price per 1,000 unique saved results |
| --- | --- |
| Free / no discount | $1.00 |
| Starter / Bronze discount | $0.95 |
| Scale / Silver discount | $0.90 |
| Business / Gold discount | $0.85 |
| Platinum discount | $0.85 |
| Diamond discount | $0.85 |

- The only billing event is **Result** (`apify-default-dataset-item`), one event per unique saved profile within each source account and relationship.
- No start event, page event, retry fee, duplicate charge or audit-record fee.
- A profile repeated within the same source account and relation is removed **before** any write or charge. The same profile in two different source audiences or relations represents two distinct records.
- Results are capped before saving. The SDK's affordable count is checked before fetching and writing. An insufficient full-request budget does not prevent a smaller affordable extraction.
- Result events are generated by the default dataset write. The Actor does not manually charge a second event.
- The result count is checked against SDK receipts and event counters. In PPE runs, `sdk_result_events_charged == results_saved` is required; mismatches stop processing for reconciliation and are never relabeled successful or retried as another write.

No separate data-service subscription is needed. Set a maximum run charge in Apify and start with a small result limit. A Free-plan quota reservation is not an extra billable event.

### Reliability and stop rules

- Sequential provider requests, with streamed page results.
- HTTP 429, 5xx, transport failures and empty responses: **at most two retries** after the first attempt, with 3- and 9-second waits. A valid larger `Retry-After` is honored up to 300 seconds. Mixed failure types share the same three-attempt total.
- Persistent 429/5xx ends that source account with a provider error; other accounts can continue.
- Three empty responses stop the **entire run** with `PROVIDER_ERROR`, retaining any results already delivered. An empty page's new cursor is not followed during retries.
- HTTP 401/403 stops all accounts with a service-access error. Contact Actor support with your run ID; you do not need to supply an additional API key.
- Missing/private accounts generate a warning and do not prevent later accounts from being processed.
- A repeated or cyclic cursor stops pagination and sets `stop_repeated_cursor`. Already fulfilling the requested result limit is still a normal `SUCCESS`.
- A missing next cursor on a non-empty page is a natural end, not a partial failure.

| Audit / OUTPUT status | Meaning |
| --- | --- |
| `SUCCESS` | Requested maximum reached, or accessible pagination ended naturally. Fewer followers than requested is not by itself an error. |
| `PARTIAL` | Some results retained but work could not complete because of budget, timeout, provider error or unavailable targets. Always includes `partial_reason`. |
| `NO_RESULTS` | No saved results without a classified failure; repeated empty provider responses are NOT classified this way. |
| `UNAVAILABLE` | Requested targets were missing/private/restricted and no results were saved. |
| `INVALID_INPUT` | No valid source or invalid configuration; no provider work. |
| `PROVIDER_ERROR` | Provider/authentication failure; can retain results saved earlier. |
| `PROCESSING_FAILED` | Processing/configuration/storage failure or interruption. |
| `LIMIT_REACHED` | Internal test request cap reached; progress is retained. This cap is not a customer input. |
| `FREE_API_DAILY_LIMIT_REACHED` / `FREE_WEB_DAILY_LIMIT_REACHED` | Free daily quota exhausted before provider work. |
| `NO_BUDGET` | Cannot afford one more result and nothing was delivered. |

These are business/audit states. Apify's platform status is separate; for example, a handled partial result may have platform status `SUCCEEDED`. Invalid input, provider errors and processing failures exit nonzero. The audit records the platform status actually known at its snapshot, not a guessed future status.

### Summary and private audit

`OUTPUT` and the final log contain per-account/relation delivery counts, rejected entry indexes/reasons, duplicates removed, request usage, account errors, stop causes and SDK result event counts.

Each orderly run attempts one final record in a dedicated, owner-restricted audit dataset. It contains counts, statuses, sanitized error details, Apify run context and `input.usernames`: the valid, normalized, deduplicated source accounts requested in the input. These are recorded before Free-plan restrictions reduce the list; they do not imply that every requested account was processed. Check `OUTPUT.accounts` for processed-account results. Input that fails configuration validation may have an empty audited username list.

In the audit, `metrics.results_delivered` is the total number of confirmed saved results across all processed accounts. It equals `metrics.results_saved` (retained for compatibility) and `billing.results_delivered`. `metrics.items_received` counts profiles received from the service before deduplication and limits; it is not the delivered count. `metrics.sdk_result_events_charged` separately records reported result events. Audit metrics contain counts, not downloaded profile rows.

**Downloaded follower/following profiles, social-profile IDs, cookies, cursors, biographies, credentials and rejected raw input are not copied into the audit.** Apify run/user/build/dataset IDs are included; they are not social-profile IDs. Existing audit records are not backfilled.

The final append is serialized and marked in the run KV store. Migration uses a non-final record and retains progress. Before the platform timeout, the Actor reserves roughly 15 seconds to checkpoint and finalize. A forced kill or storage outage can prevent any final write: there is no absolute exactly-once guarantee across separate network/storage operations. `AUDIT_PENDING` retains a sanitized recovery copy, and an ambiguous append is not blindly repeated. Audit storage failure is surfaced, not silently discarded.

### Resume without replaying saved rows

Progress is saved in `STATE` in the run's key-value store. On Apify, migration/resurrection must retain the same run, dataset and key-value store for this recovery path. The dataset rebuilds deduplication sets after an interrupted write. Counters are cumulative for that job, and completed or failed accounts are not automatically restarted.

A new run normally receives new storage and starts a new extraction. There is no cross-run continuation-token input. Do not run two workers against the same storage, and do not share `STATE` because it contains private continuation state.

**Compatibility:** this revision uses checkpoint schema 2. The older private build `0.0.1` used per-relation result limits and checkpoint schema 1. Use fresh storage when moving from that build; old checkpoints are rejected rather than silently changing billing or result limits.

Build `0.0.2` allowed a combined relationship mode. Its combined-mode checkpoints cannot resume under a single relationship; use fresh storage instead. Single-relationship schema-2 checkpoints remain compatible when the accounts and selected relationship are unchanged.

### Recommended timeout

These are conservative starting settings, not measured completion guarantees. Size means total requested records across all source accounts. Increase for many sources, retries or slow responses, while keeping a bounded timeout and run budget.

| Requested total | Suggested timeout |
| --- | --- |
| Up to 100 | 5 minutes |
| Up to 1,000 | 20 minutes |
| Up to 5,000 | 60 minutes |
| Larger / unlimited | Stage the work into bounded runs or resumptions; estimate from a small pilot first. |

For planning, approximately `pages x observed response time + retry waits + storage overhead` is needed. In our small live sample, later pages usually contained only 10 profiles. If no next page is accessible, increasing the timeout cannot reveal additional results. Large-result throughput and cloud migration have not been live-validated for this revision.

### Known limits

In a small live sample, followers pagination worked across seven pages for `neeturaj2525`. `meta`, `mosseri` and `zuck` returned approximately 50 followers without a next cursor. Following pagination worked for those tested accounts. Pages could overlap and were generally 10 profiles after the first. These observations do not prove a universal verified/business-account restriction or complete audience accessibility.

Do not assume unlimited follower downloads, fixed page sizes, access to private targets or full audience completeness, especially for large accounts. Results reflect the public profiles accessible at extraction time; they are not a guaranteed complete list.

### Responsible use and support

Use public data for lawful purposes, follow applicable platform terms, and retain only what is necessary. This Actor does not bypass private-profile controls. Contact scraping\_solutions with your run ID and sanitized summary; never share credentials, cookies or `STATE`, which contains private continuation state.

# Actor input Schema

## `usernames` (type: `array`):

Usernames or Threads profile URLs, such as meta, @meta, or https://www.threads.com/@meta. Invalid entries are rejected before provider calls and explained in OUTPUT. Duplicate accounts are processed once. Free processes only the first valid account.

## `type` (type: `string`):

Choose followers or following for all accounts in this run. To download the other relationship, start a separate run.

## `maxResultsPerUser` (type: `integer`):

Maximum saved profiles per account for the selected relationship. 0 means all available, subject to budget and Free quota. The provider may return fewer profiles or no pagination cursor.

## Actor input object example

```json
{
  "usernames": [
    "meta"
  ],
  "type": "followers",
  "maxResultsPerUser": 100
}
```

# Actor output Schema

## `results` (type: `string`):

No description

## `summary` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "usernames": [
        "meta"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("scraping_solutions/threads-followers-following-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "usernames": ["meta"] }

# Run the Actor and wait for it to finish
run = client.actor("scraping_solutions/threads-followers-following-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "usernames": [
    "meta"
  ]
}' |
apify call scraping_solutions/threads-followers-following-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,scraping_solutions/threads-followers-following-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/saj7rFAmdaZyO8FAW/builds/IAeCuuNI7rXBqsZhn/openapi.json
