OnlyFans reverse lookup: match Instagram and TikTok handles with Python
Start from a list of creators' social handles, names or profile links and find out which of them have an OnlyFans, what it costs and whether a promotion is running. Then save the matches to a CSV file.
Agencies, brands and talent managers often hold a campaign sheet, a CRM export or a list of inbound applications with creators' Instagram and TikTok links, and need to know which of those creators sell on OnlyFans. The lookup endpoint of the OnlyFans API takes one handle, name or link per call and returns the matching creator with a match confidence and the key public profile fields.
Setup
You need Python 3, requests (pip install requests) and a key from the RapidAPI listing. Put the key in an environment variable called RAPIDAPI_KEY. Usage is counted in units: a lookup costs 5 when a creator is found and 1 when not, and a profile costs 1.
import csv
import json
import os
import time
import requests
BASE = "https://onlyfans-api11.p.rapidapi.com"
HEADERS = {
"X-RapidAPI-Key": os.environ["RAPIDAPI_KEY"],
"X-RapidAPI-Host": "onlyfans-api11.p.rapidapi.com",
}
def get(path, **params):
"""GET a path and return the JSON. Retries capacity and upstream errors."""
for attempt in range(4):
response = requests.get(BASE + path, headers=HEADERS, params=params, timeout=60)
if response.status_code in (429, 502, 503) and attempt < 3:
time.sleep(2 ** attempt)
continue
response.raise_for_status()
return response.json()
Look up one handle
GET /v1/onlyfans/lookup takes one handle: @name, name, a full name such as First Last, or a profile link (Instagram, TikTok, X, Linktree and others). For a link, the username is taken from the link.
curl --request GET \
--url 'https://onlyfans-api11.p.rapidapi.com/v1/onlyfans/lookup?handle=https%3A%2F%2Fwww.instagram.com%2Fbelledelphine%2F' \
--header "X-RapidAPI-Key: $RAPIDAPI_KEY" \
--header 'X-RapidAPI-Host: onlyfans-api11.p.rapidapi.com'
Example answer with values from 2026-09-26; image link shortened, the bio fields and 21 other fields left out
{
"seed": "https://www.instagram.com/belledelphine/",
"displayInput": "belledelphine",
"seedType": "url",
"lookupHandle": "belledelphine",
"ofFound": true,
"ofUsername": "belledelphine",
"ofUrl": "https://onlyfans.com/belledelphine",
"ofName": "Belle Delphine",
"ofAvatar": "https://public.onlyfans.com/files/…/avatar.jpg",
"ofIsVerified": true,
"ofIsActive": true,
"ofIsFree": false,
"ofPrice": 35,
"ofCurrentPrice": 35,
"ofLikesCount": 1481357,
"ofPostsCount": 1033,
"ofPhotosCount": 18403,
"ofVideosCount": 759,
"ofJoinDate": "2020-05-28",
"ofLastSeen": "2026-07-20 16:12:29",
"matchConfidence": "exact",
"enrichMethod": "Direct"
}
The fields that matter for matching:
ofFound:truewhen a creator was found. A miss is still HTTP 200, withofFound: falseand noofUsername.enrichMethod:Directwhen the handle is itself an OnlyFans username;Normalwhen the creator was found through a search, which is how full names are matched.matchConfidence:exactwhen the OnlyFans username equals your handle or differs by at most 2 characters; otherwisehigh, orlowfor a weak match.ofPriceis the regular monthly price in USD andofCurrentPricethe price right now. WhenofCurrentPriceis lower, a promotion is running.ofIsFreemarks free accounts.
Look up a list
inputs = [
"https://www.instagram.com/belledelphine/",
"https://www.tiktok.com/@corinnakopf",
"@angelawhite",
"lanarhoades",
"zzqq_no_such_creator_8812",
]
results = [get("/v1/onlyfans/lookup", handle=h) for h in inputs]
with open("lookups.json", "w", encoding="utf-8") as f:
json.dump(results, f, indent=1, ensure_ascii=False) # keep the full answers
def price_text(r):
if r.get("ofIsFree"):
return "free"
regular, now = r.get("ofPrice"), r.get("ofCurrentPrice")
if regular is None:
return "no subscription price"
if now is not None and now < regular:
return f"${now:.2f} now, regular ${regular:.2f}"
return f"${regular:.2f}"
for r in results:
if r["ofFound"]:
print(f'{r["seed"]} -> {r["ofUrl"]} ({r["matchConfidence"]}): {price_text(r)}')
else:
print(f'{r["seed"]} -> not found')
Output with the values from 2026-09-26 (prices and promotions change often)
https://www.instagram.com/belledelphine/ -> https://onlyfans.com/belledelphine (exact): $35.00
https://www.tiktok.com/@corinnakopf -> https://onlyfans.com/corinnakopf (exact): $4.00 now, regular $19.99
@angelawhite -> https://onlyfans.com/angelawhite (exact): $5.00 now, regular $9.99
lanarhoades -> https://onlyfans.com/lanarhoades (exact): free
zzqq_no_such_creator_8812 -> not found
This list costs 4 × 5 + 1 = 21 units: four creators found and one miss.
See running promotions
For creators with a promotion, GET /v1/onlyfans/profile/{username} (1 unit) returns the full public profile, including promotions (price, message, end date, how many fans claimed it) and subscriptionBundles (multi-month discounts).
for r in results:
if not r["ofFound"] or r.get("ofIsFree"):
continue
if (r.get("ofCurrentPrice") or 0) < (r.get("ofPrice") or 0):
profile = get(f"/v1/onlyfans/profile/{r['ofUsername']}")
for p in profile.get("promotions") or []:
print(r["ofUsername"], p.get("price"), p.get("finishedAt"), p.get("claimsCount"))
for b in profile.get("subscriptionBundles") or []:
print(r["ofUsername"], f'{b.get("duration")} months', b.get("price"), f'{b.get("discount")}% off')
For the list above this makes 2 profile calls, one for each creator with a promotion.
Save a CSV
FIELDS = ["seed", "ofFound", "ofUsername", "ofUrl", "matchConfidence", "enrichMethod",
"ofName", "ofIsVerified", "ofIsFree", "ofPrice", "ofCurrentPrice",
"ofLikesCount", "ofPostsCount", "ofLastSeen"]
with open("onlyfans_matches.csv", "w", newline="", encoding="utf-8") as f:
writer = csv.DictWriter(f, fieldnames=FIELDS, extrasaction="ignore")
writer.writeheader()
writer.writerows(results)
The row for the TikTok link, values from 2026-09-26
https://www.tiktok.com/@corinnakopf,True,corinnakopf,https://onlyfans.com/corinnakopf,exact,Direct,Corinna Kopf,True,False,19.99,4,2771060,339,2026-09-26 17:18:02
Check each match before you act on it
A lookup matches usernames, not people. The API doesn't read the Instagram or TikTok profile: it takes the username from the link, checks OnlyFans for that username, and if there's none, searches for it. So:
exactmeans the OnlyFans username matches your handle (within 2 characters). It doesn't prove it's the same person. Before you contact anyone, confirm the link, for example through theofWebsitefield or the social links in the creator's bio.- A creator who uses a different username on OnlyFans won't be found from their handle. Try their full name as a second lookup (
enrichMethodwill beNormal). - A miss (
ofFound: false) means no match was found, not that the person has no OnlyFans.
Responsible use
Only look up creators who promote their OnlyFans publicly, or with whom you have a business relationship. Don't use lookups to expose, out or harass anyone. Keep only the fields you need, and follow the privacy law that applies to you, such as GDPR or CCPA. Bios and images on OnlyFans can contain adult content, so filter them before you show results to your team.
Things to know
- Freshness. Answers are cached for up to 7 days, so a price or promotion can be up to a week old. Confirm the live price on OnlyFans before you quote it to anyone.
- Subscriber counts are only shown when the creator makes them public, which is rare. Don't build on them.
- Errors:
400missing or invalidhandle,404unknown username (profile),429plan limit,502or503upstream temporarily unavailable (thegethelper retries). Server errors are never billed. - This API is unofficial and not affiliated with OnlyFans. It reads public profile data only; no OnlyFans account is needed.
Next steps
- API docs: creator search by keyword and full creator profiles.
- No code? Run the OnlyFans Reverse Lookup Actor on Apify: paste a list of handles, names or links and export the matches to CSV or Excel.
Plans
Plans, monthly quotas and rate limits are listed on the RapidAPI listing. For more volume or a custom plan, use Contact provider on the listing.