Threads Followers Scraper: Mutual Connection Map
Pricing
from $2.99 / 1,000 results
Threads Followers Scraper: Mutual Connection Map
๐งตโจ Threads User Followers Scraper scrapes Instagram Threads follower and following data to map relationships, mutuals, and overlaps. ๐ Export clean CSV/JSON for analytics. ๐ Perfect for competitor tracking, influencer discovery, and audience research.
Pricing
from $2.99 / 1,000 results
Rating
0.0
(0)
Developer
SimpleAPI
Maintained by CommunityActor stats
0
Bookmarked
1
Total users
0
Monthly active users
2 days ago
Last modified
Categories
Share
Threads Mutual Connection Mapper โ who actually follows back
Threads Follower Mutual Connection Mapper turns a Threads profile's follower list into a verified two-way relationship map. For every target profile it reads the real follower list and the real list of accounts that profile follows, then intersects the two follow edges: a follower found in both lists is a confirmed mutual; a follower absent from a fully-read following list is a fan. Each profile also gets a summary row with real counts and a real mutual percentage.
It is built for creators and marketers who want to know their genuine two-way audience, community managers auditing engagement quality, and researchers studying follower-network structure. A logged-in session cookie is required: Threads serves follower and following lists only to authenticated clients.
How the mutual map is computed (and why it is trustworthy)
Every node Threads returns in a followers page carries a friendship_status block. That block is viewer-relative โ it describes the relationship between the logged-in session account and that user, not between the scraped target and that user. Reading it as "the target follows them back" is simply wrong, and with a fresh session account it labels every real follower as "no relationship".
This Actor therefore computes the map from two independently fetched edges:
followers(target) โฉ following(target) = mutual connections
- Membership in
followers(target)proves the follower โ target edge. - Membership in
following(target)proves the target โ follower edge.
Two details make the result honest rather than merely plausible:
- Convergent sweeps. Threads paginates these connections with an offset cursor over a ranking that is not stable between requests, so a single sweep silently drops entries โ measured live on one account: 172 following edges in one sweep, 194 after two, 197 after three, 198 after four. A dropped edge would turn a real mutual into a fabricated "fan", so the following list is swept repeatedly until a sweep adds nothing new.
- No invented negatives. "This person is not followed back" is stated only when the following list was read to convergence. Otherwise the follower is reported as
relationshipType: "unknown"withisMutual: nullโ never as a fan. The summary reportsfollowingScanConvergedandundeterminedCountso you can see exactly how much was determined.
The raw viewer-relative flags are still exported, under names that say what they are: viewerRelationship, plus the untouched following / followed_by / outgoing_request booleans as Threads returns them.
What data can I extract?
Follower rows (recordType: "follower")
| Field | Example | Notes |
|---|---|---|
username / full_name / profile_url | guilhermenetobjj | Follower identity |
pk / user_id | 69491985527 | Threads numeric id |
is_verified / is_private | false | |
follower_count | 629 | The follower's own real follower count, or null when Threads did not return one โ never a stand-in 0 |
follower_count_source | followers_query | unknown when the count is null |
followsTarget | true | Definitional: the row came from the target's follower list |
targetFollowsBack | true / false / null | null = not determined (following list not read to convergence) |
isMutual | true / false / null | |
relationshipType | mutual, fan, unknown | |
connectionStrength | 5 | 5 mutual+verified, 4 mutual, 3 fan+verified, 2 fan, 1 undetermined |
connectionRank | 1 | Position under the chosen sortBy |
relationshipBasis | text | Says whether negatives are safe to trust |
viewerRelationship | none | Relationship to your session account, not the target |
target_username / target_user_id | dimby_soberdino | Which profile this row belongs to |
Relationship summary rows (recordType: "relationship_summary")
| Field | Example | Notes |
|---|---|---|
targetFollowerCount / targetIsVerified | 14 | The target's own real stats |
followersAnalyzed | 14 | Followers actually read |
followingEdgesSampled | 197 | Following edges read for the intersection |
followingSweeps / followingScanConverged | 3 / true | Convergence evidence |
followingListComplete | true | Whether "not mutual" verdicts are asserted |
mutualCount / fanCount / undeterminedCount | 12 / 2 / 0 | |
mutualPct | 85.71 | Share of followers with a determined relationship; null when nothing was determined |
verifiedMutualCount | 0 | |
topMutualFollowerCount / medianMutualFollowerCount | 629 / 90 | null when there are no mutuals โ never 0 |
mutualUsernames | ["guilhermenetobjj", โฆ] | Up to 200 confirmed mutuals |
rowsWritten | 14 | Rows actually saved for this profile |
๐ผ Input
| Parameter | Required | Type | Description | Default |
|---|---|---|---|---|
urls | Yes | array | Threads @usernames or profile URLs, one per line | โ |
sessionId | Yes | string (secret) | Your logged-in Threads/Instagram sessionid cookie | โ |
maxFollowers | No | integer 1โ100000 | Followers analyzed per profile | 50 |
maxFollowingLookup | No | integer 1โ100000 | How much of the target's following list to read for the intersection | 2000 |
onlyMutuals | No | boolean | Save only confirmed mutual rows | false |
sortBy | No | connection / followers / username | Row order and connectionRank | connection |
maxRunTimeSecs | No | integer 60โ86400 | Hard wall-clock budget; stops cleanly and keeps what it has | 3600 |
proxyConfiguration | No | object | Optional fallback route if a direct connection is refused | {"useApifyProxy": true} |
{"urls": ["dimby_soberdino", "https://www.threads.com/@thnkmii._"],"sessionId": "<YOUR_THREADS_SESSIONID>","maxFollowers": 50,"maxFollowingLookup": 2000,"onlyMutuals": false,"sortBy": "connection"}
sessionId is marked isSecret: true so it renders masked in the Apify Console. Never share it โ it grants live access to your Threads/Instagram account.
๐ฝ Output sample (real rows from a live run)
{"recordType": "follower","target_username": "dimby_soberdino","target_user_id": "80052535746","username": "guilhermenetobjj","full_name": "Guilherme Neto","pk": "69491985527","is_verified": false,"is_private": false,"follower_count": 629,"follower_count_source": "followers_query","followsTarget": true,"targetFollowsBack": true,"isMutual": true,"relationshipType": "mutual","connectionStrength": 4,"connectionRank": 1,"relationshipBasis": "intersection of the target's followers list and following list (following list read to convergence)","viewerRelationship": "none","profile_url": "https://www.threads.com/@guilhermenetobjj"}
{"recordType": "relationship_summary","target_username": "dimby_soberdino","targetFollowerCount": 14,"followersAnalyzed": 14,"followingEdgesSampled": 197,"followingSweeps": 3,"followingScanConverged": true,"followingListComplete": true,"mutualCount": 12,"fanCount": 2,"undeterminedCount": 0,"mutualPct": 85.71,"verifiedMutualCount": 0,"topMutualFollowerCount": 629,"medianMutualFollowerCount": 90}
How to target specific connections
onlyMutuals is the primary lever: off for the full breakdown, on for a clean outreach list. If a profile turns out to have no mutuals at all, its real rows are kept anyway (flagged isMutual: false) rather than handing you an empty dataset โ the log says so explicitly.
maxFollowingLookup controls how many relationships can be decided. Set it below the number of accounts a target follows and the scan cannot converge, so unmatched followers come back as unknown instead of fan. Raise it for accounts that follow thousands of people.
maxFollowers controls cost and how representative mutualPct is. Note that Threads serves only a ~50-follower sample for very large accounts (no continuation cursor at all), which the log states plainly; small and mid-size profiles paginate fully.
Why not build this yourself?
Threads has no public API for this. The internal GraphQL endpoint needs a persisted-query doc_id and the complete set of Relay __relay_internal__pv__*relayprovider variables โ omit one and you get HTTP 200 with data: null and a generic "execution error" (live check: the 65 flags harvested from the JS bundles work, the 32 readable from the page HTML alone do not). This Actor scrapes both doc_ids and the live provider set out of the page's own JavaScript bundles at request time, so it survives front-end deploys. It also resolves the target's numeric id from the JSON object whose username matches exactly โ a looser scan returns an unrelated constant for handles that have no Threads profile (@levelsio, @cristiano), which would silently query the wrong account.
Programmatic use
from apify_client import ApifyClientclient = ApifyClient("<YOUR_API_TOKEN>")run = client.actor("<YOUR_USERNAME>/threads-follower-mutual-connection-mapper").call(run_input={"urls": ["dimby_soberdino"],"sessionId": "<YOUR_THREADS_SESSIONID>","maxFollowers": 50,})for item in client.dataset(run["defaultDatasetId"]).iterate_items():if item.get("recordType") == "relationship_summary":print(item["target_username"], item["mutualPct"], "% mutual")
Is it legal to use?
This Actor uses your own Threads/Instagram session cookie and reads relationship data your account is already authorized to see when browsing normally. Make sure your use complies with Meta's Terms of Service, which restrict automated data collection. Follower identity fields (username, full_name) are personal data under GDPR/CCPA โ treat storage and reuse accordingly, and consult legal counsel for commercial applications.
โ FAQ
Why do I need to log in?
Threads serves follower and following lists only to authenticated clients, and it ships the friendships query module only to logged-in sessions. Without a sessionid cookie there is nothing to read.
Why is a follower marked unknown instead of fan?
Because the target's following list was not read to convergence โ it hit maxFollowingLookup, the time budget, or an API limit. Calling that follower a "fan" would be a guess, so the Actor withholds the verdict instead. Raise maxFollowingLookup and maxRunTimeSecs to decide it.
Does onlyMutuals affect the summary row?
No. The summary is computed over every follower analyzed, so mutualPct, fanCount and undeterminedCount stay meaningful regardless of what was written as rows.
Why did a huge account return only ~50 followers?
Threads returns a single capped sample with no continuation cursor for very large accounts. That is the whole sample the API offers, and the run log says so rather than pretending it is the full list.
What does connectionStrength measure?
A documented ordinal derived only from real fields: 5 = mutual and verified, 4 = mutual, 3 = fan and verified, 2 = fan, 1 = follows the target with reciprocity undetermined. It is a sorting convenience, not a metric Threads publishes.
What happens when my session cookie expires mid-run?
The Actor reports the specific failure (auth: reason) for that profile and continues. If no profile could be mapped at all, the run fails with a status message saying so โ it never reports success over an empty result.
Conclusion
This Actor turns a raw follower list into a verified two-way relationship map: real mutual/fan classification computed from two independently fetched follow edges, convergence-checked so negatives are never invented, plus an honest per-profile summary. Start a run from the Apify Console or API with your target profiles and session cookie.