I run a visa agency in Bali. The rest of my week goes into Apify Actors, and one of them turns a list of Threads handles into profile rows: followers, full name, bio, the links in the bio, verification, the HD avatar — and the date and text of the account's newest post.
That last field is the one I want to argue for. I added it because I wanted to know whether an account was alive before paying attention to it. Then I measured 30 accounts and it turned out to be the only column in the row that answers the question anybody actually has.
The measurement
One run, 19 October 2026, mode: profile, 30 handles I took off the top of Instagram — nine people, twenty-one brands and news outlets:
{
"mode": "profile",
"usernames": ["instagram", "cristiano", "leomessi", "selenagomez", "therock",
"arianagrande", "kimkardashian", "beyonce", "justinbieber", "taylorswift",
"nike", "cocacola", "starbucks", "mcdonalds", "adidas", "netflix", "spotify",
"airbnb", "zara", "sephora", "apple", "google", "microsoft", "amazon",
"cnn", "reuters", "espn", "nba", "nfl", "fifaworldcup"],
"includeProfileDetails": true
}
55 seconds, 30 rows out, $0.096 billed. Two things in that output I did not expect.
Six of the thirty have no Threads profile
leomessi profile not found or private
therock profile not found or private
cristiano profile not found or private
arianagrande profile not found or private
beyonce profile not found or private
justinbieber profile not found or private
Reproducible: I ran the same six again an hour later and got the same six error rows, all with blocked: false, so this is not a rate limit wearing a different hat.
A Threads account can only be created from an Instagram account, which is exactly why everybody — me included — assumes the handle you have is the handle you can query. It is not. Instagram handle and Threads handle are the same string when the owner opted in, and a large slice of Instagram's biggest accounts never did.
To check that these were really absent rather than private, I searched Threads' own people index for the same names. For "cristiano ronaldo", "the rock dwayne" and "beyonce", the top results were:
cristianojunction Cristiano Ronaldo Fan Page verified: false
cristiano.unofficials Cristiano.unofficials verified: false
dwaynetherockjohn Dwayne The Rock Johnson verified: false
therocknews2025 Dwayne Johnson verified: false
rumiyonce Beyoncé Fan Account verified: false
queenyoncechella BEYONCÉ FAN PAGE 🐝🤠🤍 verified: false
Eighteen results across three queries, not one of them verified, not one of them the person. Those accounts are genuinely not on Threads, and the search index agrees.
The split in my sample is sharp: 21 of 21 brands and news outlets resolved; 3 of 9 individual celebrities did (Selena Gomez, Kim Kardashian, Taylor Swift). If your pipeline is built on an Instagram-sourced list of people, expect to lose a chunk of it at the door — and expect the loss to be silent, because an error row is still a successful run.
A related trap from an earlier run: @vogue failed, while a people search for "vogue" returns voguemagazine — verified, full name "Vogue". @bbcnews failed; the BBC's Threads presence came back as @bbc. The handle in your spreadsheet can be a different account from the brand you meant, or no account at all, and both arrive as the same error string. If that matters, resolve names through search first and query handles second.
Follower count did not survive contact with the data
Here are the 24 that resolved, sorted the way everyone sorts them, with days since the newest post next to it:
| Handle | Followers | Days since last post |
|---|---|---|
| 38,328,297 | 0 | |
| selenagomez | 20,789,749 | 570 |
| kimkardashian | 17,143,885 | 959 |
| taylorswift | 16,136,367 | 23 |
| nike | 15,059,014 | 129 |
| nba | 12,215,103 | 0 |
| fifaworldcup | 12,104,356 | 0 |
| netflix | 8,608,579 | 0 |
| zara | 6,790,005 | 16 |
| cnn | 5,534,944 | 0 |
| apple | 5,023,058 | never posted |
| nfl | 4,664,185 | 0 |
| espn | 4,582,408 | 0 |
| 3,932,478 | 0 | |
| sephora | 3,390,599 | 0 |
| spotify | 3,224,261 | 0 |
| adidas | 2,874,636 | 1 |
| starbucks | 2,698,912 | 5 |
| reuters | 2,213,217 | 0 |
| amazon | 1,203,698 | 10 |
| microsoft | 1,176,406 | 167 |
| airbnb | 1,153,117 | 1,055 |
| mcdonalds | 846,900 | 0 |
| cocacola | 503,444 | 31 |
Take the top five by followers. Four of them — Selena Gomez, Kim Kardashian, Taylor Swift, Nike — have been quiet for 23 to 959 days. Only @instagram posted this week.
Now take the bottom two. McDonald's, with the smallest audience in the table, posted today. Coca-Cola posted five weeks ago.
The table holds 190.2 million follower-units. 60.8 million of them — just under a third — sit on the seven accounts that have not posted in a month, and 44.1 million on the four that have been silent for six months or longer, Apple included.
I checked the two extremes directly, in posts mode:
@apple — 5,023,058 followers, verified, no bio, zero post rows
@airbnb — 1,153,117 followers, newest post 28 November 2023
Airbnb's final Threads post is a Giving Tuesday fundraiser from almost three years ago. It got 64 likes. Apple's profile row is the stranger one:
{
"type": "profile",
"username": "apple",
"fullName": "apple",
"biography": null,
"bioLinks": [],
"followerCount": 5023058,
"isVerified": true,
"isPrivate": false,
"latestPostAt": null,
"latestPostUrl": null
}
Five million followers, no bio, no posts, verified. Whatever produced that number, it was not activity on Threads. I can't prove the mechanism from the row itself, and I'm not going to guess at one — but the observable fact is enough on its own: on Threads, a follower count can be fully decoupled from whether the account has ever used the product.
Which makes followerCount a measure of a brand's standing somewhere else, and latestPostAt the only field in the row that is about Threads.
So sort on the other column
The whole correction is about four lines after the fetch:
import requests
from datetime import datetime, timezone
rows = requests.post(
"https://api.apify.com/v2/acts/lergassy~threads-profile-scraper/run-sync-get-dataset-items",
params={"token": TOKEN},
json={"mode": "profile", "usernames": HANDLES, "includeProfileDetails": True},
).json()
now = datetime.now(timezone.utc)
live, dead, missing = [], [], []
for r in rows:
if r["type"] == "error":
missing.append(r["url"]); continue
if not r["latestPostAt"]:
dead.append((r["username"], r["followerCount"], None)); continue
age = (now - datetime.fromisoformat(r["latestPostAt"].replace("Z", "+00:00"))).days
(live if age <= 30 else dead).append((r["username"], r["followerCount"], age))
print(f"{len(live)} live, {len(dead)} stale, {len(missing)} not on Threads: {missing}")
for u, f, age in sorted(live, key=lambda x: -x[1]):
print(f"{u:<14}{f:>11,} {age}d")
On my 30 handles that prints 17 live, 7 stale, 6 not on Threads. A shortlist of 17 is a usable piece of work. A shortlist of 30 sorted by followers is a quarter wrong and tells you nothing about which quarter.
Three more fields that mean less than they look like
-
instagramUrlis derived, not verified. It ishttps://www.instagram.com/<username>/, assembled from the handle. I wrote that line; it does no lookup. Treat it as a convenience for your CRM, never as evidence that the Instagram account exists. -
emailsandphonescome out of the bio text and nowhere else. Across all 24 resolved profiles: zero emails, zero phone numbers. Big accounts don't put a mailbox in a 150-character bio. That field earns its keep on small creators and local businesses, which is where bios actually carry contacts — not on the brands you'd test it with. -
isVerifiedis not a seniority ranking.@airbnbcame backisVerified: falsewhile@applecame backtruewith an empty bio and a lowercasefullNameof "apple". Filtering a brand list on the blue tick drops real corporate accounts.
Error rows, for what it's worth, are free, and the run finishes green with them in the dataset. That is deliberate — but it also means a run can bill you for 24 rows, exit successfully, and quietly be missing six of the accounts you cared most about. Count your type: "error" rows every time.
When this is the wrong tool
- You need reach, not audience size. Follower count is the wrong proxy, as above, and view counts live on posts, not profiles. Switch to posts mode and read engagement.
-
You need a private account's posts. A private profile returns its public header with
isPrivate: trueand nothing else. That is the complete answer, not a bug to work around. - Your list is names, not handles. Resolve through search first. Handles look guessable and are not.
- You need the official API. Threads' own API covers your own account only. If you need your own analytics, use that; this reads the pages Threads serves to any logged-out visitor.
The Actor is Threads Profile Scraper — no login, no browser, $0.004 per profile, error rows free. The 30-handle run in this post took 55 seconds and cost 9.6 cents; an 80-post pull from a single account took 10.5 seconds.
If you keep one thing from this: before you rank social accounts by audience, print the date of the newest post next to the number. On Threads, seven of my twenty-four would have ranked above an account that posts daily while having nothing to say at all.
Top comments (0)