YouTube Channel API

Beta

Returns a public YouTube channel: channel ID, handle, name, description, keywords, avatar, banner, verification badge, country, join date, the links on its About panel with their labels, and its subscriber count with exact video and lifetime view counts. Accepts a handle with or without the @, any channel link with any tab (@handle, /channel/UC…, the legacy /c/, /user/ and root vanity links), or a bare channel ID.

Get 100 free creditsAPI referenceTry it

Price
From 1 credit per request$0.75–$1.45 per 1,000 requests
Request
GET /v1/youtube/profileOne API key, one JSON schema
Input
handlee.g. @NASA
Failed requests
Free: 0 credits

Use cases

What teams build with it. From one request.

  • Track channel growth over time
  • Vet creators before a sponsorship
  • Enrich lead lists with a creator's other social links
  • Resolve a video's channel ID to a full profile

What you get

Profiles in one schema. The same on every platform.

platformstring
Platform ID (tiktok, youtube, …).
idstring
Platform-native account ID (string; YouTube UC…, Reddit without 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.

Every field, its type and when it is null: the response reference and the profile schema.

Example request

cURL
curl -G 'https://staging-fly.socialtap.dev/v1/youtube/profile' \
  --data-urlencode 'handle=@NASA' \
  -H "x-api-key: $SOCIALTAP_API_KEY"
Node.js
const params = new URLSearchParams({
  handle: "@NASA",
});
const res = await fetch(`https://staging-fly.socialtap.dev/v1/youtube/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);
Python
import os

import requests

res = requests.get(
    "https://staging-fly.socialtap.dev/v1/youtube/profile",
    params={"handle": "@NASA"},
    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"])
Go
package main

import (
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"net/url"
	"os"
)

func main() {
	q := url.Values{}
	q.Set("handle", "@NASA")
	req, err := http.NewRequest("GET", "https://staging-fly.socialtap.dev/v1/youtube/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"])
}
PHP
<?php

$query = http_build_query([
    'handle' => '@NASA',
]);
$ch = curl_init('https://staging-fly.socialtap.dev/v1/youtube/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;
Ruby
require "json"
require "net/http"

uri = URI("https://staging-fly.socialtap.dev/v1/youtube/profile")
uri.query = URI.encode_www_form('handle' => '@NASA')
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"]
Java
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("@NASA");
        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create("https://staging-fly.socialtap.dev/v1/youtube/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);
    }
}
.NET
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("@NASA"));
var res = await http.GetAsync("https://staging-fly.socialtap.dev/v1/youtube/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"));
Rust
// 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://staging-fly.socialtap.dev/v1/youtube/profile")
        .query(&[("handle", "@NASA")])
        .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
{
  "data": {
    "approximate_fields": [
      "created_at",
      "metrics.follower_count"
    ],
    "avatar_url": "https://yt3.googleusercontent.com/eIf5fNPcIcj9ig-wZBeq4stFy1lgjWTW1nLT5dYlFkHZprZ03QBiMcbpwNMB6XSBjrSFGtAGQg=s900-c-k-c0x00ffffff-no-rj",
    "banner_url": "https://yt3.googleusercontent.com/y8Srh-oCcilLvBO8jAPI546m1bn0puA5DIvQiBZ1cSxc_rZfKxKSFlTCtoCQCtB6viUf1NGsaQ=w2560-fcrop64=1,00005a57ffffa5a8-k-c0xffffffff-no-nd-rj",
    "bio": "NASA's mission is to pioneer the future in space exploration, scientific discovery, and aeronautics research.\n\nTo do that, we have worked around the world—and off it—for more than 60 years, searching for answers to fundamental questions about our place in the universe. We're expl…",
    "category": null,
    "country_code": null,
    "created_at": "2008-06-03T07:00:00Z",
    "display_name": "NASA",
    "external_links": [
      {
        "title": "nasa.gov",
        "url": "https://www.nasa.gov"
      },
      {
        "title": "X",
        "url": "https://x.com/nasa"
      },
      {
        "title": "Facebook",
        "url": "https://www.facebook.com/NASA"
      }
    ],
    "id": "UCLA_DiR1FfKNvjuUpBHmylQ",
    "is_private": false,
    "is_verified": true,
    "location": null,
    "metrics": {
      "follower_count": 15100000,
      "following_count": null,
      "post_count": 6194,
      "total_like_count": null,
      "total_view_count": 1132473139
    },
    "platform": "youtube",
    "platform_specific": {
      "youtube": {
        "is_business_email_listed": null,
        "is_official_artist_channel": false,
        "is_subscriber_count_hidden": false,
        "keywords": [
          "nasa",
          "space",
          "iss"
        ]
      }
    },
    "type": "unknown",
    "unknown_fields": [],
    "url": "https://www.youtube.com/@NASA",
    "username": "NASA"
  },
  "meta": {
    "request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
    "platform": "youtube",
    "source": "api",
    "is_cached": false,
    "credits_charged": 1,
    "latency_ms": 0,
    "fetched_at": "2026-10-25T12:00:00Z",
    "input": {
      "kind": "profile",
      "id": "UCLA_DiR1FfKNvjuUpBHmylQ",
      "url": "https://www.youtube.com/@NASA"
    },
    "credits_remaining": 9999,
    "client_request_id": null,
    "warnings": [],
    "mode": "live"
  }
}

Long arrays and strings are shortened for display; real responses are complete.

Pricing

Pay per request. Only when it succeeds.

SourcePrice per successful requestPer 1,000 requests
Any source1 credit$0.75–$1.45
  • Failed requests are free: errors cost 0 credits.
  • Cache hits are free: responses served from the cache cost 0 credits.
  • Credits never expire.
  • One credit balance for every endpoint and platform.

Credit packs · How this endpoint is priced · How credits work

FAQ

Questions, answered.

How much does the YouTube Channel API cost?
1 credit, charged only for successful requests. SocialTap credits cost $0.75–$1.45 per 1,000 depending on the pack.
Am I charged for failed requests?
No. Requests that return an error cost 0 credits. Responses served from the cache are free too.

Start with 100 free credits. No card required.

Test keys answer every endpoint from recorded responses, free, so you can build before you spend. Failed requests are always free.

Get your API keyRead the API reference