Linkme Profile API. Send a handle or profile link.
Total followers, social handles and every link. We handle the proxies, blocks and platform changes.
Linkme Profile API at a glance
Returns a public Linkme profile with its total followers, each social account's handle and followers, every link and its contact details. Contact details are the emails, phone numbers and street addresses the page lists. Each link has its title, description, thumbnail and section, and a music link its destination on each streaming service. The profile adds the name, bio, picture, logo, banner, verified badge, and when it was created and last changed. Send the page's name or link.
GET /v1/linkme/profile
- 1 credit per request, $0.75–$1.97 per 1,000 requests
- 19 typed fields null when unknown
handleis all it needs, e.g.papisteak- 100 credits free when you sign up, no card, so you can build before you spend
Send one request. Get 19 fields back.
Copy the request in your language, or hand it to your agent. Sign up for an API key and your first 100 credits are free.
$ npm install socialtaphandle = papisteakconst params = new URLSearchParams({
handle: "papisteak",
});
const res = await fetch(`https://socialtap.dev/v1/linkme/profile?${params}`, {
headers: { "x-api-key": process.env.SOCIALTAP_API_KEY ?? "" },
});
const body = await res.json();
if (!res.ok) throw new Error(`${body.error.code}: ${body.error.message}`);
const { data, meta } = body;
console.log(data, meta.credits_charged);import os
import requests
res = requests.get(
"https://socialtap.dev/v1/linkme/profile",
params={"handle": "papisteak"},
headers={"x-api-key": os.environ["SOCIALTAP_API_KEY"]},
)
body = res.json()
if not res.ok:
raise RuntimeError(f"{body['error']['code']}: {body['error']['message']}")
data, meta = body["data"], body["meta"]
print(data, meta["credits_charged"])require "json"
require "net/http"
uri = URI("https://socialtap.dev/v1/linkme/profile")
uri.query = URI.encode_www_form('handle' => 'papisteak')
req = Net::HTTP::Get.new(uri)
req["x-api-key"] = ENV.fetch("SOCIALTAP_API_KEY")
res = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == "https") { |http| http.request(req) }
body = JSON.parse(res.body)
raise "#{body["error"]["code"]}: #{body["error"]["message"]}" unless res.is_a?(Net::HTTPSuccess)
pp body["data"]
puts body["meta"]["credits_charged"]<?php
$query = http_build_query([
'handle' => 'papisteak',
]);
$ch = curl_init('https://socialtap.dev/v1/linkme/profile?' . $query);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['x-api-key: ' . getenv('SOCIALTAP_API_KEY')],
]);
$body = json_decode(curl_exec($ch), true);
if (curl_getinfo($ch, CURLINFO_RESPONSE_CODE) >= 400) {
throw new RuntimeException($body['error']['code'] . ': ' . $body['error']['message']);
}
print_r($body['data']);
echo $body['meta']['credits_charged'], PHP_EOL;package main
import (
"encoding/json"
"fmt"
"log"
"net/http"
"net/url"
"os"
)
func main() {
q := url.Values{}
q.Set("handle", "papisteak")
req, err := http.NewRequest("GET", "https://socialtap.dev/v1/linkme/profile?"+q.Encode(), nil)
if err != nil {
log.Fatal(err)
}
req.Header.Set("x-api-key", os.Getenv("SOCIALTAP_API_KEY"))
res, err := http.DefaultClient.Do(req)
if err != nil {
log.Fatal(err)
}
defer res.Body.Close()
var body struct {
Data json.RawMessage `json:"data"`
Meta map[string]any `json:"meta"`
Error *struct {
Code string `json:"code"`
Message string `json:"message"`
} `json:"error"`
}
if err := json.NewDecoder(res.Body).Decode(&body); err != nil {
log.Fatal(err)
}
if body.Error != nil {
log.Fatalf("%s: %s", body.Error.Code, body.Error.Message)
}
fmt.Println(string(body.Data), body.Meta["credits_charged"])
}curl 'https://socialtap.dev/v1/linkme/profile?handle=papisteak' \
-H "x-api-key: $SOCIALTAP_API_KEY"{
"data": {
"approximate_fields": [
"platform_specific.linkme.profile_visit_count"
],
"avatar_url": "https://media.link.me/images/user-profile/2123271/tmp-565-1766183620379.png",
"banner_url": null,
"bio": "Iconic high-energy Steakhouse",
"category": null,
"country_code": null,
"created_at": "2025-12-19T19:47:40Z",
"display_name": "Papi Steak",
"external_links": [
{
"title": "Instagram",
"url": "https://www.instagram.com/papisteak"
},
{
"title": "Facebook",
"url": "https://www.facebook.com/papisteakmiami/"
},
{
"title": "Threads",
"url": "https://www.threads.net/@papisteak?igshid=NTc4MTIwNjQ2YQ=="
}
],
"id": "2123271",
"is_private": false,
"is_verified": true,
"location": null,
"metrics": {
"follower_count": 239913,
"following_count": null,
"post_count": null,
"total_like_count": null,
"total_view_count": null
},
"platform": "linkme",
"platform_specific": {
"linkme": {
"emails": [],
"featured_links": [
{
"description": null,
"group": null,
"id": "1688371",
"image_url": "https://media.link.me/images/external-links/2123271/1793642723656.png",
"is_adult": false,
"platform": "link",
"platforms": [],
"section": null,
"title": "Doordash",
"url": "https://order.online/business/24734529/store/51360639"
},
{
"description": null,
"group": null,
"id": "686462",
"image_url": "https://media.link.me/images/external-links/2123271/1766177538178.jpeg",
"is_adult": false,
"platform": "link",
"platforms": [],
"section": null,
"title": "Website",
"url": "https://papisteak.com/"
},
{
"description": null,
"group": null,
"id": "686481",
"image_url": "https://media.link.me/images/external-links/2123271/1766177573005.jpeg",
"is_adult": false,
"platform": "link",
"platforms": [],
"section": "PAPI STEAK MIAMI BEACH",
"title": "Menu",
"url": "https://papisteak.com/miami/menu/"
}
],
"is_adult": false,
"link_count": 16,
"linkme_connection_count": 2,
"locations": [],
"logo_url": "https://media.link.me/images/logo-image/2123271/tmp-2241-1778613564542.png",
"network_follower_count": 239911,
"phones": [],
"profile_visit_count": 15400,
"social_links": [
{
"follower_count": 194575,
"handle": "papisteak",
"is_adult": false,
"platform": "Instagram",
"url": "https://www.instagram.com/papisteak"
},
{
"follower_count": 7900,
"handle": "papisteakmiami",
"is_adult": false,
"platform": "Facebook",
"url": "https://www.facebook.com/papisteakmiami/"
},
{
"follower_count": 37436,
"handle": "papisteak",
"is_adult": false,
"platform": "Threads",
"url": "https://www.threads.net/@papisteak?igshid=NTc4MTIwNjQ2YQ=="
}
],
"updated_at": "2026-08-28T22:13:02Z"
}
},
"type": "unknown",
"unknown_fields": [],
"url": "https://link.me/papisteak",
"username": "papisteak"
},
"meta": {
"request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
"platform": "linkme",
"source": "api",
"is_cached": false,
"credits_charged": 1,
"latency_ms": 281,
"fetched_at": "2026-10-25T12:00:00Z",
"input": {
"kind": "profile",
"id": "2123271",
"url": "https://link.me/papisteak"
},
"credits_remaining": 9999,
"client_request_id": null,
"warnings": []
}
}import { SocialTap } from "socialtap";
const client = new SocialTap(); // apiKey defaults to process.env.SOCIALTAP_API_KEY
const res = await client.linkme.profile.get({ handle: "papisteak" });
console.log(res.data);
console.log(res.credits.charged, res.meta.request_id);import java.net.URI;
import java.net.URLEncoder;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
public class Main {
public static void main(String[] args) throws Exception {
String query = "handle=" + encode("papisteak");
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://socialtap.dev/v1/linkme/profile?" + query))
.header("x-api-key", System.getenv("SOCIALTAP_API_KEY"))
.GET()
.build();
HttpResponse<String> response = HttpClient.newHttpClient()
.send(request, HttpResponse.BodyHandlers.ofString());
// An error is {"error": {"code", "message", ...}}; success is {data, meta}, meta.credits_charged its price.
if (response.statusCode() >= 400) throw new RuntimeException(response.body());
System.out.println(response.body());
}
static String encode(String value) {
return URLEncoder.encode(value, StandardCharsets.UTF_8);
}
}using System.Text.Json;
using var http = new HttpClient();
http.DefaultRequestHeaders.Add("x-api-key", Environment.GetEnvironmentVariable("SOCIALTAP_API_KEY"));
var query = string.Join("&",
"handle=" + Uri.EscapeDataString("papisteak"));
var res = await http.GetAsync("https://socialtap.dev/v1/linkme/profile?" + query);
using var body = JsonDocument.Parse(await res.Content.ReadAsStringAsync());
if (!res.IsSuccessStatusCode)
{
var error = body.RootElement.GetProperty("error");
throw new Exception($"{error.GetProperty("code")}: {error.GetProperty("message")}");
}
Console.WriteLine(body.RootElement.GetProperty("data"));
Console.WriteLine(body.RootElement.GetProperty("meta").GetProperty("credits_charged"));// Cargo.toml: reqwest = { version = "0.12", features = ["blocking", "json"] }, serde_json = "1"
use std::env;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let res = reqwest::blocking::Client::new()
.get("https://socialtap.dev/v1/linkme/profile")
.query(&[("handle", "papisteak")])
.header("x-api-key", env::var("SOCIALTAP_API_KEY")?)
.send()?;
let ok = res.status().is_success();
let body: serde_json::Value = res.json()?;
if !ok {
return Err(format!("{}: {}", body["error"]["code"], body["error"]["message"]).into());
}
println!("{} {}", body["data"], body["meta"]["credits_charged"]);
Ok(())
}200 OK · GET https://socialtap.dev/v1/linkme/profileLong arrays and strings are shortened here. Real responses are complete.Docs One schema on 27 platforms.
The response reference lists every field, its type and when it is null. See the full schema.
Null means unknown
A field Linkme doesn't show is null, never zero or an empty string, so a real zero always means zero.
What it accepts
The Linkme page: its name (papisteak, with or without the @) or its link (https://link.me/papisteak).
Write one parser
Linkme, TikTok, Instagram and 24 more platforms answer in these fields, so the code that reads one reads them all.
platformstring- Platform ID (tiktok, youtube, …).
idstring- Platform-native account ID (string; YouTube UC…, Reddit t2_…).
usernamestring- Handle without the @; null when the account has none.
display_namestring- Display name, channel title or page name; null when empty or not exposed.
urlstring- Canonical profile URL.
typestring- Coarse account kind, as the platform labels it; unknown when it does not (TikTok labels organizations only). New values may be added; treat unknown values as unknown.
biostring- Profile bio, channel description or page about text; null when empty or not exposed.
avatar_urlstring- Profile picture URL (largest available). Platform CDN URLs can expire within hours.
Live data from 33 platforms.
What teams build with the Linkme Profile API.
Measure a creator's total reach in one request
Find a creator's handle on each network
Find a venue's phone number and street address
Track the offers and releases a creator promotes
Good to know before you build.
- metrics.follower_count is the page's Total Followers, unrounded: network_follower_count (from the networks the account connected) plus linkme_connection_count (the Links in the page's followers sheet), both in platform_specific.linkme.
- follower_count is null when the page has no total, as on most accounts. Their icons in social_links can still carry follower counts of their own, which we never add up.
- Linkme shows the total only on verified accounts' pages, but an unverified account's total is in the page's data and is returned too.
- external_links holds every web link on the page once: social icons, the contact block's website, then the link list with each carousel card and music destination. Emails, phones and street addresses are in platform_specific.linkme.
- What an account hides from its page (bio, icons, link list, contact block or total followers) is not returned, though Linkme's data holds it.
- Event tickets, shop products, courses, videos and photos are other parts of the page and are not returned.
- An icon can hold a name to copy instead of a link (an Xbox gamertag, a Zelle name). Its url is then null and handle has the name.
- Links Linkme marks as adult open after a notice any visitor can pass, so they are returned like the others, with is_adult true.
- A page that shows "This page is locked" returns private_or_unavailable.
- A private account's page shows only the name, picture and icons, and so do we: is_private is true, bio and follower_count are null, and the link and contact lists are in unknown_fields.
- type is unknown, and category, country_code and the other metrics are null: Linkme has none of them.
- A name no account has, or an account Linkme removed, returns not_found. Names of Linkme's own pages (pricing, login) are refused as input.
1 credit per request. Failed requests are free.
Buy credits once and spend them on any endpoint, on any platform.
| Source | Price per successful request | Per 1,000 requests |
|---|---|---|
Platform API api | 1 credit | $0.75–$1.97 |
Public page page | 1 credit | $0.75–$1.97 |
- Cache hits are free.
- Credits from packs and top-ups never expire.
- A monthly plan's credits are spent first, and what is left of them ends at each renewal.
- Prices exclude tax: sales tax is added at checkout where it applies.
- Outside the US, plans and packs are sold to businesses: checkout asks for your VAT, GST or other business tax ID.
Questions about the Linkme Profile API.
More in the API reference.
Is Total Followers the sum of the creator's social accounts?
Does it return links marked as adult content?
How much does the Linkme Profile API cost?
Try it on an account you know.
Paste its handle or link in the playground, or copy the request into your code.
- No credit card
- Failed requests are free
- Works on all 218 endpoints