Best influencer outreach API: accounts, email, and id
Seven calls cost 48 credits. The best influencer outreach api leaves contact_email null when a bio has no address, and stores the stable YouTube channel id.
The best influencer outreach api for a growth marketer about to email someone is four calls: candidate accounts for a name, the creator's own email only when the profile text supports that choice, the YouTube about payload, and the stored channel id. Check that id before you treat a handle that fails to resolve as a removed channel.
CreatorDB, InfluenceFlow, and Influencer Hero, the pages ranking for this query, are discovery-database lists. A creator discovery api in that shape is a catalogue. The calls below are what you run once you already have a person or a brand name.
Those seven GETs ran on the SocialCrawl API on 2026-10-11, from 16:18:03Z to 16:18:21Z, and they cost 48 credits. The Instagram contact field came back null. The YouTube about address is also written in the biography. No rename was observed. The brief-check charge of 15 credits is still marked provisional.
How do you find accounts with an influencer marketing api?
You pass a name, a type, and the platforms to search. On 2026-10-11 the call was name=MrBeast, type=person, platforms=twitter,instagram,tiktok, and candidates=3.
curl "https://www.socialcrawl.dev/v1/prism/find-accounts?name=MrBeast&type=person&platforms=twitter,instagram,tiktok&candidates=3" \
-H "x-api-key: $SOCIALCRAWL_API_KEY"HTTP 200, cached false, credits_used 6. Three platforms came back, three candidates each. Response order is Instagram, then TikTok, then X. The query string listed twitter, then instagram, then tiktok.
Leading handles are Instagram mrbeast, TikTok mrbeast, and X MrBeast. On each leader, match.level is same, match.basis is judged, and match.handle is the rank-1 candidate. Confidence is 0.88 on Instagram, 0.95 on TikTok, and 0.94 on X. automated_decision is present and false. data._warnings is absent, not an empty list.
The notice says: "Candidate accounts ranked from public search results, for human review. A match level is an automated label, not proof of who runs an account; your reviewer decides. Private accounts are not listed."
{
"credits_used": 6,
"cached": false,
"data": {
"automated_decision": false,
"notice": "Candidate accounts ranked from public search results, for human review. A match level is an automated label, not proof of who runs an account; your reviewer decides. Private accounts are not listed.",
"platforms": [
{
"platform": "instagram",
"match": { "handle": "mrbeast", "level": "same", "basis": "judged" }
},
{
"platform": "tiktok",
"match": { "handle": "mrbeast", "level": "same", "basis": "judged" }
},
{
"platform": "twitter",
"match": { "handle": "MrBeast", "level": "same", "basis": "judged" }
}
]
}
}With a known name on those three platforms, you are using this endpoint as an influencer search api. Rank 2 and rank 3 stay on the list for a person to reject.
| Platform | Rank | Handle | Followers | choice_probability |
|---|---|---|---|---|
| 1 | mrbeast | null | 1 | |
| 2 | mr..beast..104 | null | 0 | |
| 3 | mr_beast_00986 | null | 0 | |
| tiktok | 1 | mrbeast | 143721548 | 1 |
| tiktok | 2 | beast_clip7 | 214343 | 0 |
| tiktok | 3 | mrbeast.sigma_ | 771132 | 0 |
| 1 | MrBeast | 34987011 | 1 | |
| 2 | MrBeastExtra | 386249 | 0 | |
| 3 | MrBeastBurger | 190395 | 0 |
Instagram followers is null on all three rows. TikTok rank 1 is 143721548 followers. X rank 1 is 34987011. Instagram and TikTok bio_excerpt values are null. Rank 1 on X is "I want to make the world a better place". Rank 2 is "this is my place to be stupid. Main - @mrbeast". Rank 3, MrBeast Burger, is "big flavor by @mrbeast. smashed burgers, crispy chicken sandwiches, outrageous grilled cheese, seasoned crinkle fries & more. delivering nationwide."
choice_probability is 1 on each rank 1 and 0 on the other six rows, MrBeast Burger included. Those rows are there so a reviewer can reject them. same with basis judged is a label from public search. The payload is a candidate list for a reviewer, and automated_decision false leaves that decision with the person reading it.
Evidence on every leader is website_match false, cross_link false, bio_consistent true, and fan_or_parody false. coverage is 1. partial_failure is false. context.employer, context.location, and context.website are null. methodology_version is find-accounts-v1. LinkedIn was not requested. Private accounts are left out.
The search legs on the body are /v1/instagram/search/profiles at 1 credit, /v1/tiktok/search/users at 1 credit, and /v1/twitter/search/users at 1 credit. The legs sum to 3. The envelope credits_used is 6. The other 3 match the price checked before the call, 1 judge credit on each of the three platforms. candidates=3 is outside that formula. The leg credits sit inside the 6. Adding them again would count the searches twice.
When is contact_email the creator's own address, and when do you keep public_email?
The Instagram call used the official account, handle instagram, with contact_email=1.
curl "https://www.socialcrawl.dev/v1/instagram/profile?handle=instagram&contact_email=1" \
-H "x-api-key: $SOCIALCRAWL_API_KEY"HTTP 200, credits_used 1, cached false. 1 is the registry price of instagram/profile. This run did not also fetch the profile without the flag, so there is no measured delta for the flag. The only measured charge is 1.
author.id is 25025320, the username is instagram, the display name is Instagram, verified is true, and private is false. followers is 686593882. The bio is exactly Discover what's new on Instagram 🔎✨, 35 characters, and it contains no email address. business_category is null.
author.ext.contact_email is present and null. author.ext.public_email is absent. The key is missing from the body. A missing key is a different state from a key set to null.
{
"credits_used": 1,
"cached": false,
"data": {
"author": {
"id": "25025320",
"username": "instagram",
"display_name": "Instagram",
"bio": "Discover what's new on Instagram 🔎✨",
"verified": true,
"private": false,
"followers": 686593882,
"ext": {
"business_category": null,
"contact_email": null
}
}
}
}contact_email is the creator's own address only when the text lists two or more addresses and one of them is clearly the creator's own. The field stays null for a single address, for no address, for a manager, agency, brand, or sponsor, and when the choice is unclear. On calls that already have an address, public_email stays the first one. No sample addresses are attached to the rule, because this run did not capture a two-address bio.
This body is the none case. contact_email is null, and the public_email key is missing. A one-address bio was not captured, and neither was a body whose public_email held a first address. The same is true of a manager, agency, brand, sponsor, or unclear choice. A creator email finder that supplies an address this bio does not contain is outside this call.
For the Instagram bio address alone, see how that public email is read. That post is Instagram public-email extraction. This one is the workflow around find-accounts, contact_email, channel about, and a stored channel id. The profile route lives on the Instagram docs. The same parameter is legal on youtube/channel and youtube/channel/about. This harvest did not send contact_email on those calls, so this section stops at Instagram.
The rejected value was measured on the same handle.
curl "https://www.socialcrawl.dev/v1/instagram/profile?handle=instagram&contact_email=2" \
-H "x-api-key: $SOCIALCRAWL_API_KEY"HTTP 400, credits_used 0. cached is absent. error.type is INVALID_REQUEST. There is no error.code. details.invalid_parameters lists contact_email. details.allowed_values lists 1. The message allows only 1, and the response below quotes it.
{
"success": false,
"error": {
"type": "INVALID_REQUEST",
"message": "Invalid value for 'contact_email': '2'. Allowed values: 1. Did you mean '1'? Example: contact_email=1.",
"details": {
"invalid_parameters": ["contact_email"],
"allowed_values": ["1"]
}
},
"credits_used": 0
}Where does the YouTube View email address come back?
On GET /v1/youtube/channel/about the address is author.ext.public_email, beside the biography and the profile links. The 2026-10-11 call used handle mkbhd.
curl "https://www.socialcrawl.dev/v1/youtube/channel/about?handle=mkbhd" \
-H "x-api-key: $SOCIALCRAWL_API_KEY"HTTP 200, cached false, credits_used 25, and an address was present. The registry price checked before the call is 25 when an address is returned and 0 when none is. This run did not call a channel with no address, so that 0-credit miss was not measured.
author.ext.public_email is business@mkbhd.com, a business address on mkbhd.com. The biography is 128 characters and already spells business@MKBHD.com, different case from the field. Both strings are on the same 200, so this run does not say whether the field was taken from the biography or from the View email address control.
contact_email was not sent. author.ext.contact_email is absent on this response.
Marques Brownlee, username @mkbhd, id UCBJycsmduvYEL83R_U4JriQ, is verified, joined on 2008-03-21, and is listed in the United States, with posts_count 1857, total_views 5755895689, and followers 21400000. followers_approximate is true, so 21400000 is not an exact subscriber count.
author.ext.links has five URLs, in this order: https://twitter.com/MKBHD, https://instagram.com/MKBHD, https://youtube.com/c/TheStudio, https://reddit.com/r/MKBHD, https://discord.gg/MKBHD.
The biography, as returned:
MKBHD: Quality Tech Videos | YouTuber | Geek | Consumer Electronics | Tech Head | Internet Personality!
business@MKBHD.com
NYC{
"credits_used": 25,
"cached": false,
"data": {
"author": {
"id": "UCBJycsmduvYEL83R_U4JriQ",
"username": "@mkbhd",
"display_name": "Marques Brownlee",
"bio": "MKBHD: Quality Tech Videos | YouTuber | Geek | Consumer Electronics | Tech Head | Internet Personality!\n\nbusiness@MKBHD.com\n\nNYC",
"verified": true,
"followers": 21400000,
"posts_count": 1857,
"joined_at": "2008-03-21",
"ext": {
"country": "United States",
"public_email": "business@mkbhd.com",
"followers_approximate": true,
"total_views": 5755895689,
"links": [
"https://twitter.com/MKBHD",
"https://instagram.com/MKBHD",
"https://youtube.com/c/TheStudio",
"https://reddit.com/r/MKBHD",
"https://discord.gg/MKBHD"
]
}
}
}
}Channel and channel-about routes are on the YouTube docs.
How do you tell a rename from a removed channel with the stored channel id?
Call A is a stored channel id. Call B is a handle this run had never resolved. Call A was not a retry of call B.
Call A:
curl "https://www.socialcrawl.dev/v1/youtube/channel?channelId=UCX6OQ3DkcsbYNE6H8uQQuVA" \
-H "x-api-key: $SOCIALCRAWL_API_KEY"HTTP 200, cached false, credits_used 1. author.id is UCX6OQ3DkcsbYNE6H8uQQuVA, the id that was sent. author.username is @mrbeast. The display name is MrBeast. A 200 on that stored id means the channel is still there. No older YouTube handle was resolved in this run, so @mrbeast is the current username on that id, and this run did not watch a handle change.
author.ext.public_email is present and null. The biography is 998 characters and contains no @. youtube/channel/about was not called for this channel, so this 1-credit response cannot tell you whether MrBeast publishes a contact address. followers is 521000000 with followers_approximate true. posts_count is 1006. Country is US. joined_at is 2012-02-20.
{
"credits_used": 1,
"cached": false,
"data": {
"author": {
"id": "UCX6OQ3DkcsbYNE6H8uQQuVA",
"username": "@mrbeast",
"display_name": "MrBeast",
"followers": 521000000,
"posts_count": 1006,
"joined_at": "2012-02-20",
"ext": {
"country": "US",
"public_email": null,
"followers_approximate": true
}
}
}
}Call B, the handle that never resolved here:
curl "https://www.socialcrawl.dev/v1/youtube/channel?handle=scghostxq7k2m9pnotachannel" \
-H "x-api-key: $SOCIALCRAWL_API_KEY"HTTP 404, credits_used 0. cached is absent. error.type is RESOURCE_NOT_FOUND. error.details.reason is account_gone. The message says the request was not charged. The suggestion says channel ids stay put when handles change. Call /v1/youtube/channel with channelId set to the author.id you already hold, the id starting with UC. A 200 on that retry carries the new handle in author.username. A second 404 means the channel is gone. The response below quotes the suggestion.
{
"success": false,
"error": {
"type": "RESOURCE_NOT_FOUND",
"message": "The platform reports no account under this identifier. It has been removed or deactivated, the name was changed, or it never existed. You were not charged for this request.",
"details": {
"reason": "account_gone",
"suggestion": "YouTube channel ids are permanent while handles are not. Call `/v1/youtube/channel` with `channelId` set to the `author.id` you already hold (the id starting with UC): a 200 means the channel changed its handle and the response carries the new one in `author.username`, and a second 404 means the channel is genuinely gone."
}
},
"credits_used": 0
}scghostxq7k2m9pnotachannel was never a live channel in this run, so account_gone here means the platform did not resolve that string. The 200 above is a different input. This run did not observe a rename, did not hold both URLs across 14 days, and did not send a second 404 against a previously live id. YouTube's channels.list quota of 1 unit is a YouTube counter, not a SocialCrawl credit. The SocialCrawl credit on these two calls was 1 on the 200 and 0 on the 404.
When is a brief-check worth calling before you send?
Only when you already have a public URL and the points you need covered. It is optional. Skip it and the four calls above are still the send path. Nothing in this call was posted, edited, or taken down.
The call that ran used one public YouTube URL and two points. forbidden was not sent. require_disclosure was not sent.
curl -G "https://www.socialcrawl.dev/v1/prism/brief-check" \
-H "x-api-key: $SOCIALCRAWL_API_KEY" \
--data-urlencode "url=https://www.youtube.com/watch?v=jNQXAC9IVRw" \
--data-urlencode "points=Mention the elephants,Describe the animals"HTTP 200, cached false, envelope credits_used 15. no_transcript is false. verdict is pass. forbidden_hits is an empty list. disclosed is false. require_disclosure was not sent, so that false value was not scored as a disclosure check.
The levels are 2.26 for "Mention the elephants" and 2.07 for "Describe the animals". Both quotes are the same cut-off string. The response stops at really..., and the block below copies the quote without finishing it.
{
"credits_used": 15,
"cached": false,
"data": {
"url": "https://www.youtube.com/watch?v=jNQXAC9IVRw",
"points": [
{
"point": "Mention the elephants",
"level": 2.26,
"quote": "Me at the zoo All right, so here we are, in front of the elephants the cool thing about these guys is that they have really..."
},
{
"point": "Describe the animals",
"level": 2.07,
"quote": "Me at the zoo All right, so here we are, in front of the elephants the cool thing about these guys is that they have really..."
}
],
"forbidden_hits": [],
"disclosed": false,
"no_transcript": false,
"verdict": "pass"
}
}The legs /v1/youtube/video and /v1/youtube/video/transcript each returned HTTP 200 with credits_used 0. The billed amount is the envelope 15. Leave the leg zeros out of that 15. verdict pass covers these two points on this one URL. no_transcript false means the call had a transcript. The registry description still says "15 credits per post (provisional)." This call was charged 15. The two figures match on this run, and the price stays provisional. The route is on the Prism docs.
How do you start using this?
Get a SocialCrawl key. No signup grant was measured, so none is listed here. Put the key in $SOCIALCRAWL_API_KEY and send it on the x-api-key header. One API key covers the seven GETs.
The first call is the find-accounts request above. Then send the other six query strings: Instagram profile with contact_email=1, the same profile with contact_email=2, youtube/channel/about for mkbhd, youtube/channel with the stored channel id, the ghost handle, and the brief-check URL if you want that optional step. Read credits_used on each body. Call GET /v1/credits/balance before the batch and again after.
If your influencer data api stores a YouTube row by handle, also store author.id from the 1-credit channel call. An influencer outreach tool is a seat you log into, and these calls stop before anyone sends mail. Wiring this best influencer outreach api into a review queue starts with the find-accounts GET.
What was measured on 2026-10-11?
The window is 2026-10-11T16:18:03Z through 2026-10-11T16:18:21Z. The seven data calls were sent together, so credits_remaining on those bodies is not a sequence. Spend is 48. The arithmetic is 6+1+0+25+1+0+15. The balance moved from 38660 to 38612, the same 48. recent_deductions moved from 997 to 1003, a delta of 6, and that delta is not the spend.
Give youtube/channel/about an HTTP timeout of at least 300 seconds. This run returned inside that short batch window. A first read of an address can take longer.
From there, open the visual explorer, then the docs for Prism, Instagram, YouTube, and endpoint pricing. Check the 6, the 1, the 0, the 25, the 1, and the 15 against that pricing page. Keep the 15 provisional.
What should you confirm before you send?
Does find-accounts verify that an account is theirs, or is it a list for a person to review?
It returns a list for a person to review. On the MrBeast call, automated_decision is false. The three leaders are match.level same and match.basis judged, and data._warnings is absent. The notice says the level is a label and the reviewer decides. Rank 2 and rank 3 stay on the list, including MrBeast Burger, with choice_probability 0 against 1 on each leader.
Why does contact_email stay empty when the bio has only one address?
contact_email stays null for one address, for none, for a manager, agency, brand, or sponsor, and when the choice is unclear. The field fills only when the text lists two or more addresses and one is the creator's own. This run is the none case. The official Instagram bio has no email, contact_email is present and null, and the call used 1 credit. A one-address bio was not captured. contact_email=2 on the same handle returned HTTP 400 at 0 credits, error.type INVALID_REQUEST, with the only allowed value set to 1.
How is contact_email different from public_email?
On that Instagram body, contact_email is present and null, and public_email is not a key on the body. A missing key is a different state from a key set to null. public_email stays the first address on calls that have one. contact_email fills only when two or more addresses are listed and one is the creator's own. This run did not return a filled Instagram public_email. The mkbhd about call has public_email business@mkbhd.com and did not send contact_email, so contact_email is absent there.
Where does YouTube return the address behind View email address?
On GET /v1/youtube/channel/about?handle=mkbhd, author.ext.public_email is business@mkbhd.com, HTTP 200, 25 credits. The biography is 128 characters and already spells business@MKBHD.com, and author.ext.links has five URLs. This run does not separate the View email address control from the biography. Both strings sit on the same response. A no-address about call, the registry's 0-credit case when no address comes back, was not measured. The 1-credit youtube/channel call is a different endpoint. On channel id UCX6OQ3DkcsbYNE6H8uQQuVA, public_email is null, and channel about was not called for that channel.
How do you tell a renamed YouTube channel from one that is gone?
A handle the platform does not resolve returns HTTP 404, reason account_gone, at 0 credits. The suggestion says to call /v1/youtube/channel again with channelId set to the stored author.id, the id that starts with UC. A 200 means the channel is still there and author.username is the current handle. A second 404 means the channel is gone. In this harvest the 200 used channelId=UCX6OQ3DkcsbYNE6H8uQQuVA. author.id is that same id, author.username is @mrbeast, and the call cost 1 credit. The 404 is handle scghostxq7k2m9pnotachannel, a string that was never a live channel here. No rename was observed. The two calls are different inputs, so there is no before-and-after handle to copy from them.
Is brief-check required, and is its credit price final?
Brief-check is optional, and the 15-credit price is still provisional. The call that ran used one public YouTube URL and two points, returned HTTP 200, and charged 15 credits. no_transcript is false, verdict is pass, and the levels are 2.26 and 2.07. The registry description still says "15 credits per post (provisional)." The legs /v1/youtube/video and /v1/youtube/video/transcript each show credits_used 0. Leave those zeros out of the 15. Skip the call when you do not already have a public URL and the points you need covered.
Related posts
Best API for product review sentiment: 5 credits
Ten Amazon reviews came back labelled at 5 credits. The best API for product review sentiment is that review page, and turning labels off still cost 5.
Social Listening Leads API: Commenters Who Want to Buy
A social listening leads api returned 0 leads from 25 Figma comments, 14 serum leads (10 were price asks or pp), 20 ranked pages, and labels on 20 rows.
Best Multi-Platform Social Search API: 129 Rows, 4 Credits
Best multi-platform social search API: one coldplay call returned 129 rows from TikTok, Instagram, YouTube, and Reddit. Four sources were billed 1 credit each.
