# Meta Threads Scraper, Posts, Profiles and Engagement Data (`george.the.developer/threads-scraper`) Actor

Threads scraper for public Threads by Meta profiles and posts. Extract post text, likes, replies, reposts, media links and follower counts with no login or cookies. Monitor brands, track competitors and study trending content. Export JSON or CSV.

- **URL**: https://apify.com/george.the.developer/threads-scraper.md
- **Developed by:** [George Kioko](https://apify.com/george.the.developer) (community)
- **Categories:** Social media, Marketing
- **Features:** Limited permissions
- **Stats:** 145 total users, 8 monthly users, 100.0% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

from $9.60 / 1,000 profile scrapeds

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 Scraper - Scrape Threads by Meta Posts & Profiles (No Login Required)

Scrape public [Threads by Meta](https://www.threads.net) profiles and posts without any login, cookies, or API key. This **Instagram Threads scraper** extracts post text, engagement data (likes, replies, reposts), media URLs, follower counts, and more from any public profile on Meta's Threads platform. Use it for **Threads monitoring**, **Threads analytics**, brand tracking, influencer research, and competitive intelligence.

[![Threads Scraper on Apify](https://img.shields.io/badge/Apify-Threads%20Scraper-blue)](https://apify.com/george.the.developer/threads-scraper)

### Features

- **No login required** - Scrape Threads data without any account, cookies, or Meta Threads API key
- **Threads profile scraper** - Extract display name, bio, follower/following counts, verified status, profile picture, and link in bio
- **Threads post scraper** - Get full post text, timestamps, media URLs (images, videos, carousels), hashtags, and @mentions
- **Threads engagement data** - Capture like counts, reply counts, and repost counts for every post
- **Search functionality** - Search for posts by keyword across all of Threads
- **Single post extraction** - Scrape any individual Threads post by URL
- **Threads monitoring** - Schedule recurring runs to track brand mentions and competitor activity
- **Threads analytics** - Export structured data for engagement rate analysis and content research
- **GraphQL interception** - Captures Threads' internal API responses for accurate, structured data
- **DOM fallback** - Automatically falls back to DOM extraction when API interception is unavailable
- **Handles pagination** - Infinite scroll support to load hundreds of posts per profile
- **Anti-detection** - Residential proxies and randomized delays to avoid rate limiting

### How the Threads Scraper Works

This **Threads crawler** uses a dual-extraction strategy: it first attempts to intercept Threads' internal GraphQL API responses via Chrome DevTools Protocol, then falls back to DOM parsing if needed. No Meta Threads API access or authentication is required.

```mermaid
flowchart TD
    A[User Input: usernames, URLs, or search query] --> B[Puppeteer launches headless browser]
    B --> C[Navigate to Threads profile/post/search page]
    C --> D{Page loads with React hydration}
    D --> E[CDP Network Listener intercepts GraphQL API responses]
    D --> F[Auto-scroll triggers infinite scroll pagination]
    F --> E
    E --> G{GraphQL data captured?}
    G -->|Yes| H[Parse structured post & profile data from API response]
    G -->|No| I[DOM Fallback: extract data from rendered HTML]
    H --> J[Normalize & format output]
    I --> J
    J --> K[Filter: exclude replies/reposts if configured]
    K --> L[Push to Apify Dataset]
    L --> M[Output: JSON with posts, profiles, engagement metrics]
```

### Scraping Architecture

The Threads data extraction pipeline uses network-level interception combined with browser rendering to reliably scrape Threads without login credentials.

```mermaid
flowchart LR
    subgraph Input
        U[Usernames]
        T[Thread URLs]
        S[Search Query]
    end

    subgraph Browser["Puppeteer Browser Engine"]
        direction TB
        CDP[Chrome DevTools Protocol]
        NI[Network Interceptor]
        CDP --> NI
        NI -->|Captures| GQL[GraphQL / Barcelona API responses]
        RENDER[Page Renderer]
        RENDER -->|If no API data| DOM[DOM Extractor]
    end

    subgraph Processing
        direction TB
        PROFILE[Profile Parser\nname, bio, followers, verified]
        POSTS[Post Parser\ntext, media, timestamps]
        ENGAGE[Engagement Parser\nlikes, replies, reposts]
    end

    subgraph Output
        DS[Apify Dataset]
        API[REST API]
        SHEETS[Google Sheets]
        WEBHOOK[Webhooks]
    end

    U --> Browser
    T --> Browser
    S --> Browser
    GQL --> Processing
    DOM --> Processing
    Processing --> DS
    DS --> API
    DS --> SHEETS
    DS --> WEBHOOK
```

### Use Cases

- **Social media monitoring** - Track what's being said about your brand on Threads
- **Influencer analysis** - Evaluate influencer reach, engagement rates, and content quality on Threads
- **Competitive intelligence** - Monitor competitor activity and messaging on Meta Threads
- **Content research** - Find trending topics, hashtags, and content formats
- **Brand tracking** - Monitor brand mentions across multiple Threads profiles
- **Market research** - Understand audience sentiment and engagement patterns
- **Threads analytics dashboard** - Feed scraped data into BI tools for visualization
- **Lead generation** - Discover active accounts in your niche on Threads by Meta

### Input

| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `usernames` | Array of strings | `[]` | Threads usernames to scrape (without @). Example: `["zuck", "instagram"]` |
| `threadUrls` | Array of strings | `[]` | Direct URLs to specific Threads posts |
| `searchQuery` | String | `""` | Search for posts containing this text |
| `scrapePosts` | Boolean | `false` | Enable post scraping for profile usernames |
| `maxPosts` | Integer | `5` | Maximum posts to scrape per user when post scraping is enabled (1-50) |
| `includeReplies` | Boolean | `false` | Include reply posts in results |
| `includeReposts` | Boolean | `false` | Include reposted content in results |
| `proxyConfiguration` | Object | Apify Residential | Proxy settings |

#### Input Example - Scrape Threads Profiles

```json
{
    "usernames": ["zuck", "instagram"],
    "scrapePosts": false,
    "includeReplies": false,
    "includeReposts": false
}
```

#### Input Example - Scrape Threads Profiles and Recent Posts

```json
{
    "usernames": ["zuck", "instagram"],
    "scrapePosts": true,
    "maxPosts": 10,
    "includeReplies": false,
    "includeReposts": false
}
```

#### Input Example - Search Threads Posts

```json
{
    "searchQuery": "artificial intelligence",
    "maxPosts": 10
}
```

#### Input Example - Scrape a Single Threads Post

```json
{
    "threadUrls": ["https://www.threads.net/@zuck/post/ABC123"]
}
```

### Output

The Threads scraper outputs two types of records to the default dataset:

#### Profile Data

```json
{
    "type": "profile",
    "username": "zuck",
    "displayName": "Mark Zuckerberg",
    "bio": "Building the future of social connection.",
    "followerCount": 12500000,
    "followingCount": 450,
    "profilePicUrl": "https://...",
    "isVerified": true,
    "linkInBio": "https://about.meta.com",
    "profileUrl": "https://www.threads.net/@zuck",
    "scrapedAt": "2026-03-12T10:00:00.000Z"
}
```

#### Post Data

```json
{
    "type": "post",
    "username": "zuck",
    "postText": "Excited about the future of AI and open source.",
    "postUrl": "https://www.threads.net/@zuck/post/ABC123",
    "postedAt": "2026-03-11T15:30:00.000Z",
    "likeCount": 45000,
    "replyCount": 2300,
    "repostCount": 1200,
    "mediaUrls": ["https://..."],
    "mediaType": "image",
    "hashtags": ["#AI"],
    "mentions": ["@meta"],
    "quotedPost": null,
    "isReply": false,
    "isRepost": false,
    "scrapedAt": "2026-03-12T10:00:00.000Z"
}
```

### Output Fields Reference

| Field | Type | Description |
|-------|------|-------------|
| `type` | String | Either `"profile"` or `"post"` |
| `username` | String | Threads username |
| `displayName` | String | Display name (profile only) |
| `bio` | String | Profile bio (profile only) |
| `followerCount` | Number | Follower count (profile only) |
| `followingCount` | Number | Following count (profile only) |
| `profilePicUrl` | String | Profile picture URL (profile only) |
| `isVerified` | Boolean | Whether the account has a verified badge (profile only) |
| `linkInBio` | String | Link in bio (profile only) |
| `postText` | String | Full text content of the post |
| `postUrl` | String | Direct URL to the post |
| `postedAt` | String | ISO 8601 timestamp of when the post was created |
| `likeCount` | Number | Number of likes |
| `replyCount` | Number | Number of replies |
| `repostCount` | Number | Number of reposts/shares |
| `mediaUrls` | Array | URLs of attached images or videos |
| `mediaType` | String | Type of media: `"text"`, `"image"`, `"video"`, or `"carousel"` |
| `hashtags` | Array | Hashtags found in the post text |
| `mentions` | Array | @mentions found in the post text |
| `quotedPost` | Object | Info about a quoted post (if any) |
| `isReply` | Boolean | Whether this post is a reply |
| `isRepost` | Boolean | Whether this post is a repost |
| `scrapedAt` | String | ISO 8601 timestamp of when the data was scraped |

### How It Works - Step by Step

1. **Page rendering** - Uses Puppeteer to render Threads pages (the React app requires JavaScript execution)
2. **GraphQL interception** - Captures Threads' internal Barcelona/GraphQL API responses via Chrome DevTools Protocol for reliable, structured data
3. **DOM fallback** - Falls back to DOM extraction if API interception doesn't capture sufficient data
4. **Pagination** - Automatically scrolls to load more posts via infinite scroll
5. **Rate limiting** - Randomized delays (3-6 seconds) between requests to avoid detection and respect Threads' servers

### Pricing

This Threads scraper uses pay-per-event pricing:

- **$0.00005 per run start**, charged once when the run passes the margin guard and starts scraping
- **$0.01 per profile scraped**, $10 per 1,000 profiles (from November 5, 2026 the profile price is $0.012, $12 per 1,000 profiles)
- **$0.10 per post scraped**, $100 per 1,000 posts
- No charge for failed, skipped, or margin-guarded requests
- Runs that are estimated to be margin-negative are skipped before proxy/browser startup and return a no-charge diagnostic row
- Try it free on the [Apify platform](https://apify.com/george.the.developer/threads-scraper)

No card needed to try it. Apify's free plan includes $5 of monthly platform usage, which covers about 500 profiles here.

### Integrations

Connect this Threads data extraction tool with your existing workflow:

- **Google Sheets** - Export Threads posts and profiles directly to a spreadsheet
- **Slack / Discord** - Set up notifications for new Threads posts from monitored profiles
- **Zapier / Make** - Connect to 1000+ apps for automated Threads monitoring workflows
- **REST API** - Access results programmatically via the Apify API
- **Webhooks** - Get notified when a scraping run completes
- **Python / Node.js** - Use the Apify client libraries to integrate Threads data into your application

### Limitations

- **Public profiles only** - Private Threads profiles are detected and skipped with a warning
- **No login required** - This means the scraper can only access publicly available Threads data
- **Rate limits** - Threads may temporarily block requests if too many are made; the actor uses residential proxies and randomized delays to minimize this
- **Search** - Threads search functionality may return limited results compared to direct profile scraping

### Tips for Best Results

1. **Start small** - Test with a single username and 10-20 posts before scaling up
2. **Use residential proxies** - The default configuration uses Apify residential proxies for best reliability
3. **Respect rate limits** - Avoid scraping the same Threads profile too frequently
4. **Filter by type** - Use `includeReplies` and `includeReposts` to get exactly the data you need
5. **Schedule runs** - Set up recurring runs for ongoing Threads monitoring and analytics
6. **Export to Sheets** - Use the Google Sheets integration for quick Threads engagement data analysis

### For AI agents (MCP)

Add this actor to Claude, Cursor or any MCP client through the Apify MCP server. The URL below preloads only this actor as a tool.

```
https://mcp.apify.com?tools=george.the.developer/threads-scraper
```

A minimal input the agent can send

```json
{ "usernames": ["zuck"], "scrapePosts": true, "maxPosts": 5 }
```

### FAQ

#### Is a Threads account or Meta Threads API key required?

No. This Threads scraper works without any login, cookies, or API key. It only accesses publicly available data on threads.net.

#### Can I scrape private Threads profiles?

No. The scraper only extracts data from public Threads profiles. Private profiles are automatically detected and skipped.

#### How much does it cost to scrape Threads?

The Threads scraper charges $0.00005 per run start, $0.01 per profile scraped, and $0.10 per post scraped. From November 5, 2026 a profile costs $0.012. One profile with its 10 most recent posts costs $1.01. There is no charge for failed, skipped, or margin-guarded requests.

#### Can I use this for Threads monitoring and analytics?

Yes. Schedule recurring runs on Apify to continuously monitor Threads profiles and track engagement data over time. Export results to Google Sheets or your analytics platform via the API.

#### How does the scraper handle Threads' anti-bot measures?

The scraper uses residential proxies, randomized delays between requests, and realistic browser fingerprints. It renders pages with Puppeteer (a real Chromium browser) and intercepts data at the network level, making it difficult to distinguish from normal browsing.

#### What is the difference between GraphQL interception and DOM fallback?

GraphQL interception captures the raw API responses that Threads sends to the browser, providing the most accurate and complete data (exact like counts, timestamps, media URLs). DOM fallback parses the rendered HTML directly, which works when API interception is unavailable but may yield less precise engagement counts.

#### Can I scrape Threads search results?

Yes. Use the `searchQuery` input field to search for posts containing specific keywords across all of Threads. Results include the same post data fields as profile scraping.

#### How many Threads posts can I scrape at once?

You can scrape up to 50 posts per profile in a single run while the actor uses browser rendering and residential proxy by default. For larger jobs, split work across smaller runs or use a dedicated data pipeline.

#### Does this work as a Meta Threads API alternative?

Yes. Since Meta does not offer a public Threads API for data extraction, this scraper serves as a reliable alternative for accessing Threads post data, profile information, and engagement metrics programmatically.

### Related Tools

If you need scrapers for other platforms, check out these tools by the same developer:

- **[Google Scholar Scraper](https://apify.com/george.the.developer/google-scholar-scraper)** - Scrape academic papers, citations, and author profiles from Google Scholar
- **[Telegram Channel Scraper](https://apify.com/george.the.developer/telegram-channel-scraper)** - Extract messages, media, and metadata from public Telegram channels

Browse all scrapers by [george.the.developer on Apify](https://apify.com/george.the.developer).

# Changelog

This Actor's version history is a separate document: https://apify.com/george.the.developer/threads-scraper/changelog.md

# Actor input Schema

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

List of Threads usernames to scrape (without the @ symbol). Example: \["zuck", "instagram"]

## `threadUrls` (type: `array`):

Direct URLs to specific Threads posts to scrape. Example: \["https://www.threads.net/@zuck/post/ABC123"]

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

Search for posts containing this text. Note: Threads search requires rendering the search page.

## `scrapePosts` (type: `boolean`):

Enable post scraping for profile usernames. Leave disabled for faster profile-only lookups.

## `maxPosts` (type: `integer`):

Maximum number of posts to scrape per username when post scraping is enabled.

## `includeReplies` (type: `boolean`):

Include reply posts in results.

## `includeReposts` (type: `boolean`):

Include reposted content in results.

## `proxyConfiguration` (type: `object`):

Select proxies to use for scraping.

## Actor input object example

```json
{
  "usernames": [
    "zuck"
  ],
  "scrapePosts": true,
  "maxPosts": 3,
  "includeReplies": false,
  "includeReposts": false,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

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

Rows of this run's dataset in the Overview table view, with type, username, post text, post url, likes, replies, reposts and posted at.

# 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": [
        "zuck"
    ],
    "scrapePosts": true,
    "maxPosts": 3
};

// Run the Actor and wait for it to finish
const run = await client.actor("george.the.developer/threads-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": ["zuck"],
    "scrapePosts": True,
    "maxPosts": 3,
}

# Run the Actor and wait for it to finish
run = client.actor("george.the.developer/threads-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": [
    "zuck"
  ],
  "scrapePosts": true,
  "maxPosts": 3
}' |
apify call george.the.developer/threads-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,george.the.developer/threads-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/eGTJ4xiuraJuXnlVw/builds/Vi6mcfqOG1H6vVJzi/openapi.json
