100 크레딧 무료, 카드 등록 없이지금 시작하기
Logo
YouTube logo
100 크레딧 무료, 카드 등록 없이

YouTube Search Advanced API

필터를 모두 열어둔 영상 검색 결과를 돌려줍니다: 정렬 기준, 길이, 라이브 여부, 라이선스, 카테고리, 국가, 언어, 게시 기간.

GET /v1/youtube/search/advanced

2026년 11월 업데이트SocialCrawl 팀이 직접 관리해요

YouTube Search Advanced API는 언제 쓰나요

단순 키워드 검색으로는 범위가 너무 넓을 때 사용하세요. 결과는 늘 영상이라 채널이나 재생목록도 받으려면 search를 쓰세요.

API 레퍼런스 영문 원문

Searches YouTube videos with the full filter set: sort order, duration, live/upcoming event_type, Creative-Commons license, category, region, language, and published_after/published_before date windows: returning video id, title, thumbnail, channel, and publish time, plus a cursor for the next page. Results are always videos. This is the reliable lane for date-window, sort, and page-size work. published_after/published_before take exact RFC-3339 bounds and are genuinely applied (/v1/youtube/search's coarse uploadDate buckets are silently dropped by that upstream whenever a type is also set); order=date is an exact sort (measured: zero inversions); order=viewCount is YouTube's popularity-weighted ranking: strongly view-correlated with the top result leading, but not strictly descending, so with includeExtras=true sort the page client-side on engagement.views for exact ranking (the counts are in the response); and max_results returns up to the page size you ask for, 1-50 (exact when YouTube has the supply). Every result carries an exact per-second published_at. Set includeExtras=true to add view/like/comment counts and duration_seconds to every result (+5 credits per page), without it those are null, because YouTube's search index returns snippets only. Send include=channel to add each result's channel subscriber count (post.ext.author_followers) in the same call (1 credit per distinct channel, at most 5 per page); the two combine. SHORTS: there is no type=shorts here and there cannot be. YouTube's Data API has no Shorts concept, so no filter can distinguish a vertical Short from any other video. The documented APPROXIMATION is duration=short (under 4 minutes) plus includeExtras=true and a client-side filter on post.content.duration_seconds <= 180; it will include short landscape videos, so treat it as a narrowing heuristic, not a Shorts filter. For a real Shorts shelf use /v1/youtube/search?type=shorts, which reads YouTube's own Shorts surface and carries its own caveats.

75개 플랫폼을 병렬로 검색합니다

·TikTok logoTikTok·Instagram logoInstagram·YouTube logoYouTube·Facebook logoFacebook·X logoX·LinkedIn logoLinkedIn·Reddit logoReddit·Threads logoThreads·Pinterest logoPinterest·Twitch logoTwitch·Truth Social logoTruth Social·Snapchat logoSnapchat·Kick logoKick·Bluesky logoBluesky·Kwai logoKwai·Rumble logoRumble·Spotify logoSpotify·Apple Music logoApple Music·TikTok Shop logoTikTok Shop·Amazon Shop logoAmazon Shop·Google Shopping logoGoogle Shopping·Trustpilot logoTrustpilot·TripAdvisor logoTripAdvisor·Yelp logoYelp·Linktree logoLinktree·Komi logoKomi·Pillar logoPillar·lnk.bio logolnk.bio·Facebook Ads logoFacebook Ads·Google Ads logoGoogle Ads·LinkedIn Ads logoLinkedIn Ads·Google Search logoGoogle Search·Google News logoGoogle News·Finance logoFinance·Polymarket logoPolymarket·Tavily logoTavily·Hacker News logoHacker News·GitHub logoGitHub·Perplexity logoPerplexity·Naver logoNaver·Utility logoUtility·Universal Search logoUniversal Search
·TikTok logoTikTok·Instagram logoInstagram·YouTube logoYouTube·Facebook logoFacebook·X logoX·LinkedIn logoLinkedIn·Reddit logoReddit·Threads logoThreads·Pinterest logoPinterest·Twitch logoTwitch·Truth Social logoTruth Social·Snapchat logoSnapchat·Kick logoKick·Bluesky logoBluesky·Kwai logoKwai·Rumble logoRumble·Spotify logoSpotify·Apple Music logoApple Music·TikTok Shop logoTikTok Shop·Amazon Shop logoAmazon Shop·Google Shopping logoGoogle Shopping·Trustpilot logoTrustpilot·TripAdvisor logoTripAdvisor·Yelp logoYelp·Linktree logoLinktree·Komi logoKomi·Pillar logoPillar·lnk.bio logolnk.bio·Facebook Ads logoFacebook Ads·Google Ads logoGoogle Ads·LinkedIn Ads logoLinkedIn Ads·Google Search logoGoogle Search·Google News logoGoogle News·Finance logoFinance·Polymarket logoPolymarket·Tavily logoTavily·Hacker News logoHacker News·GitHub logoGitHub·Perplexity logoPerplexity·Naver logoNaver·Utility logoUtility·Universal Search logoUniversal Search
·TikTok logoTikTok·Instagram logoInstagram·YouTube logoYouTube·Facebook logoFacebook·X logoX·LinkedIn logoLinkedIn·Reddit logoReddit·Threads logoThreads·Pinterest logoPinterest·Twitch logoTwitch·Truth Social logoTruth Social·Snapchat logoSnapchat·Kick logoKick·Bluesky logoBluesky·Kwai logoKwai·Rumble logoRumble·Spotify logoSpotify·Apple Music logoApple Music·TikTok Shop logoTikTok Shop·Amazon Shop logoAmazon Shop·Google Shopping logoGoogle Shopping·Trustpilot logoTrustpilot·TripAdvisor logoTripAdvisor·Yelp logoYelp·Linktree logoLinktree·Komi logoKomi·Pillar logoPillar·lnk.bio logolnk.bio·Facebook Ads logoFacebook Ads·Google Ads logoGoogle Ads·LinkedIn Ads logoLinkedIn Ads·Google Search logoGoogle Search·Google News logoGoogle News·Finance logoFinance·Polymarket logoPolymarket·Tavily logoTavily·Hacker News logoHacker News·GitHub logoGitHub·Perplexity logoPerplexity·Naver logoNaver·Utility logoUtility·Universal Search logoUniversal Search
·TikTok logoTikTok·Instagram logoInstagram·YouTube logoYouTube·Facebook logoFacebook·X logoX·LinkedIn logoLinkedIn·Reddit logoReddit·Threads logoThreads·Pinterest logoPinterest·Twitch logoTwitch·Truth Social logoTruth Social·Snapchat logoSnapchat·Kick logoKick·Bluesky logoBluesky·Kwai logoKwai·Rumble logoRumble·Spotify logoSpotify·Apple Music logoApple Music·TikTok Shop logoTikTok Shop·Amazon Shop logoAmazon Shop·Google Shopping logoGoogle Shopping·Trustpilot logoTrustpilot·TripAdvisor logoTripAdvisor·Yelp logoYelp·Linktree logoLinktree·Komi logoKomi·Pillar logoPillar·lnk.bio logolnk.bio·Facebook Ads logoFacebook Ads·Google Ads logoGoogle Ads·LinkedIn Ads logoLinkedIn Ads·Google Search logoGoogle Search·Google News logoGoogle News·Finance logoFinance·Polymarket logoPolymarket·Tavily logoTavily·Hacker News logoHacker News·GitHub logoGitHub·Perplexity logoPerplexity·Naver logoNaver·Utility logoUtility·Universal Search logoUniversal Search
YouTube API

Search Advanced API로 무엇을 할 수 있을까요

Search Advanced 엔드포인트가 통합 스키마와 계산 필드를 담은 YouTube 데이터를 한 번의 요청으로 보내드려요. 스크래핑 인프라를 직접 만들거나 유지할 필요가 없어요.

요청 예시

# GET /v1/youtube/search/advanced: Metered: holds 1 credit per page up front and refunds what the call does not use. Cache hits are free and failed calls are refunded.
# Check the price first for 0 credits: add dry_run=1 to the query. Nothing is fetched or charged.
# --max-time 10: this endpoint's measured p99 latency x 1.5.
# --retry 3: retries timeouts, 429 and 5xx, honoring Retry-After.
# -o response.json keeps only the final attempt's body.
# One Idempotency-Key per request, reused on every retry, so a retried call is never charged twice.
# Next page: send pagination.next_cursor back as cursor until pagination.has_more is false.
IDEMPOTENCY_KEY=$(od -An -N16 -tx1 /dev/urandom | tr -d ' \n')
curl -sS --max-time 10 --retry 3 -o response.json \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Idempotency-Key: $IDEMPOTENCY_KEY" \
  "https://www.socialcrawl.dev/v1/youtube/search/advanced?query=lofi+hip+hop&duration=long" && cat response.json
# GET /v1/youtube/search/advanced: Metered: holds 1 credit per page up front and refunds what the call does not use. Cache hits are free and failed calls are refunded.
# Check the price first for 0 credits: add dry_run=1 to the query. Nothing is fetched or charged.
import os
import random
import time
import uuid

import requests

API_KEY = os.environ.get("SOCIALCRAWL_API_KEY", "YOUR_API_KEY")
TIMEOUT_S = 10  # this endpoint's measured p99 latency x 1.5.
MAX_RETRIES = 3
URL = "https://www.socialcrawl.dev/v1/youtube/search/advanced"


def backoff(attempt):
    # Exponential backoff with jitter: about 1 s, 2 s, then 4 s.
    return 2 ** attempt * (0.5 + random.random() / 2)


def socialcrawl(params):
    # One Idempotency-Key per request, reused on every retry, so a retried call is never charged twice.
    idempotency_key = str(uuid.uuid4())
    for attempt in range(MAX_RETRIES + 1):
        try:
            res = requests.get(
                URL,
                params=params,
                headers={"x-api-key": API_KEY, "Idempotency-Key": idempotency_key},
                timeout=TIMEOUT_S,
            )
            body = res.json()
        except (requests.RequestException, ValueError):
            # A timeout, a dropped connection or a non-JSON gateway page: retry with the same key.
            if attempt == MAX_RETRIES:
                raise
            time.sleep(backoff(attempt))
            continue
        if body["success"]:
            return body
        error = body["error"]
        # Branch on error["type"], never on the message text.
        if error["type"] == "RESOURCE_NOT_FOUND":
            return None  # refunded: nothing to read
        retry_after = res.headers.get("Retry-After")
        # SERVICE_UNAVAILABLE without Retry-After is a withdrawn endpoint: permanent.
        permanent = error["type"] == "SERVICE_UNAVAILABLE" and retry_after is None
        if not error.get("retryable") or permanent or attempt == MAX_RETRIES:
            raise RuntimeError(f"{error['type']}: {error['message']} (request_id {body['request_id']})")
        # Retry-After (seconds) wins; otherwise back off.
        time.sleep(float(retry_after) if retry_after else backoff(attempt))


params = {
    "query": "lofi hip hop",
    "duration": "long",
}

# Walk the list: send pagination.next_cursor back as cursor until has_more is false.
MAX_PAGES = 10  # each page is one call
items = []
for _ in range(MAX_PAGES):
    body = socialcrawl(params)
    if body is None:
        break
    items.extend(body["data"]["items"])
    page = body.get("pagination") or {}
    if not page.get("has_more") or not page.get("next_cursor"):
        break
    params["cursor"] = page["next_cursor"]
print(f"{len(items)} items")
// GET /v1/youtube/search/advanced: Metered: holds 1 credit per page up front and refunds what the call does not use. Cache hits are free and failed calls are refunded.
// Check the price first for 0 credits: add dry_run=1 to the query. Nothing is fetched or charged.
const API_KEY = process.env.SOCIALCRAWL_API_KEY ?? "YOUR_API_KEY";
const TIMEOUT_MS = 10_000; // this endpoint's measured p99 latency x 1.5.
const MAX_RETRIES = 3;

type Page = { next_cursor: string | null; has_more: boolean };
type SocialCrawlResponse =
  | { success: true; data: any; pagination?: Page; credits_used: number; request_id: string }
  | { success: false; error: { type: string; message: string; retryable: boolean }; request_id: string };

const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
// Exponential backoff with jitter: about 1 s, 2 s, then 4 s.
const backoffMs = (attempt: number) => 2 ** attempt * 1000 * (0.5 + Math.random() / 2);

async function socialcrawl(url: URL) {
  // One Idempotency-Key per request, reused on every retry, so a retried call is never charged twice.
  const idempotencyKey = crypto.randomUUID();
  for (let attempt = 0; ; attempt++) {
    let res: Response;
    let body: SocialCrawlResponse;
    try {
      res = await fetch(url, {
        headers: {
          "x-api-key": API_KEY,
          "Idempotency-Key": idempotencyKey,
        },
        signal: AbortSignal.timeout(TIMEOUT_MS),
      });
      body = (await res.json()) as SocialCrawlResponse;
    } catch (error) {
      // A timeout, a dropped connection or a non-JSON gateway page: retry with the same key.
      if (attempt >= MAX_RETRIES) throw error;
      await sleep(backoffMs(attempt));
      continue;
    }
    if (body.success) return body;
    // Branch on error.type, never on the message text.
    if (body.error.type === "RESOURCE_NOT_FOUND") return null; // refunded: nothing to read
    const retryAfter = res.headers.get("Retry-After");
    // SERVICE_UNAVAILABLE without Retry-After is a withdrawn endpoint: permanent.
    const permanent = body.error.type === "SERVICE_UNAVAILABLE" && retryAfter === null;
    if (!body.error.retryable || permanent || attempt >= MAX_RETRIES) {
      throw new Error(`${body.error.type}: ${body.error.message} (request_id ${body.request_id})`);
    }
    // Retry-After (seconds) wins; otherwise back off.
    await sleep(retryAfter ? Number(retryAfter) * 1000 : backoffMs(attempt));
  }
}

const url = new URL("https://www.socialcrawl.dev/v1/youtube/search/advanced");
url.searchParams.set("query", "lofi hip hop");
url.searchParams.set("duration", "long");

// Walk the list: send pagination.next_cursor back as cursor until has_more is false.
const MAX_PAGES = 10; // each page is one call
const items: unknown[] = [];
for (let page = 0; page < MAX_PAGES; page++) {
  const body = await socialcrawl(url);
  if (!body) break;
  items.push(...body.data.items);
  const next = body.pagination?.next_cursor;
  if (!body.pagination?.has_more || !next) break;
  url.searchParams.set("cursor", next);
}
console.log(`${items.length} items`);

파라미터

파라미터필수설명
query예Search query.
order아니오Sort order: date, rating, relevance (default), title, videoCount, viewCount. `order=date` is exact (measured: zero inversions against the timestamps). `order=viewCount` is YouTube's popularity-weighted ranking: the top result is the true maximum but mid-list order is approximate, so for exact ranking add `includeExtras=true` and sort the page on `engagement.views` client-side. Both are far more faithful than `/v1/youtube/search`'s `sortBy=popular`, which is not view-ordered at all.
duration아니오Video length: short (<4m), medium (4-20m), long (>20m), any. Genuinely applied (unlike `/v1/youtube/search`'s `duration`, which the upstream ignores). `short` plus a client-side `post.content.duration_seconds <= 180` filter is the documented Shorts approximation: see the endpoint description for why it is an approximation and not a Shorts filter.
event_type아니오Broadcast type: live, upcoming, completed.
license아니오License filter: creativeCommon, youtube, any.
category아니오YouTube video category id (e.g. 10 = Music).
region아니오ISO 3166-1 alpha-2 country code.
language아니오Preferred result language (ISO 639-1).
published_after아니오RFC-3339 datetime lower bound (e.g. 2026-01-01T00:00:00Z). Exact and genuinely applied. This is the endpoint to use for date-window work.
published_before아니오RFC-3339 datetime upper bound. Exact and genuinely applied.
channel_id아니오Restrict results to a single channel id.
max_results아니오Maximum number of videos to return (1-50). Honored exactly: a page of 50 returns 50 (live-verified).
cursor아니오Pagination cursor from a previous response: fetches the next page.
safe_search아니오Safe-search filter: none, moderate, strict.
video_caption아니오Caption filter: any, closedCaption, none.
video_definition아니오Quality filter: any, high, standard.
video_dimension아니오Dimension filter: 2d, 3d, any.
video_embeddable아니오Restrict to embeddable videos: true, any.
video_type아니오Type filter: any, episode, movie.
topic_id아니오Restrict to a Freebase topic id (e.g. /m/04rlf for music).
location아니오Latitude,longitude center for a geo search (e.g. 37.42307,-122.08427). Must be used together with location_radius.
location_radius아니오Radius around location with a unit suffix (e.g. 50km, 10mi). Must be used together with location.
includeExtras아니오Set to `true` to add the view, like and comment counts (`post.engagement.views` / `.likes` / `.comments`) and the video length (`post.content.duration_seconds`) to every result. Left off, those four are null. YouTube's search index returns snippets only, so the counts come from a second lookup. Costs +5 credits per page (a page is at most 50 results, so it is a flat +5, not per result) and adds one upstream round-trip. If that lookup fails the page still returns, un-hydrated, with the +5 refunded and `_warnings: ["extras_unavailable"]` on the response.
include아니오Set to `channel` (one token only) to add each row's channel stats in this one call. `channel` puts the channel's subscriber count on `post.ext.author_followers` (YouTube's own figure, which it rounds to three significant figures above 1,000) and fills the channel's `post.author.display_name`, `.avatar_url` and `.username` where missing. It also adds the country the channel's owner set, as an ISO 3166-1 alpha-2 code on `post.ext.author_country` (null when the channel sets none). Each join costs 1 credit per distinct video or channel it filled, and never more than 5 per 50; ids that could not be filled are refunded. Each join adds 0.2 to 0.7 seconds on a fresh page (one lookup per 50 ids, never more than 8 seconds). Read `data.hydration` for the rows, lookups, credits held and kept, and the time. (channel)
exact_dates아니오Free views, likes, comments and channel handle are on by default and cost no credit: every result is joined to one per-video lookup (`post.engagement.views` / `.likes` / `.comments`, `post.content.duration_seconds`) and one per-channel lookup (`post.author.username`, `.display_name`, `.avatar_url`), a page at a time, adding about 0.2 to 0.7 seconds each (never more than 3). Dates are exact on this endpoint either way. Set to `false` to skip both lookups and get the snippet-only rows. A row a lookup could not fill keeps its nulls, and `_warnings` carries `stats_partial` or `stats_unavailable` (counts) and `handle_partial` or `handle_unavailable` (handle). The subscriber count stays `include=channel`. (true | false)
since아니오Only rows published on or after this date: YYYY-MM-DD (midnight UTC) or an ISO 8601 timestamp. Rows older than it are left off the page, and the page that reaches one ends the walk: `next_cursor` is not returned and `pagination.stopped_at` is `since`. Sending it sets the newest-first sort shown in this endpoint's sort parameter (any other sort value is a free 400). The page still costs what a page costs, so you pay for the pages you walk and no more. A row with no date is kept. `published_after`, `start_date`, `from_date`, `publish_time` (`yesterday`, `this-week`, `this-month`, `last-3-months`, `last-6-months`) and `max_age_days` are accepted and applied as `since`.
until아니오Only rows published on or before this date: YYYY-MM-DD (that whole UTC day is included) or an ISO 8601 timestamp. Newer rows are left off each page and the walk does not stop, so older pages follow. A row with no date is kept. `published_before`, `end_date` and `to_date` are accepted and applied as `until`.
min_views아니오Keep only rows with at least this many views (`post.engagement.views`). A row whose view count is unknown is discarded, so every returned row meets the floor. Filtering runs on our side after each page is fetched, so every page walked is billed as usual; `data.walk.discarded` counts what was removed and why. Each page is its own entry in `GET /v1/credits/transactions`, under the page's request id listed in `data.walk.request_ids`.
max_age_days아니오Keep only rows published within this many days (`post.published_at`), 1 to 3650. A row with no date is discarded. Filtering runs on our side after each page is fetched, so every page walked is billed as usual; `data.walk.discarded` counts what was removed and why. Each page is its own entry in `GET /v1/credits/transactions`, under the page's request id listed in `data.walk.request_ids`.
sort_rows아니오`views`: orders the kept rows by view count, highest first. Rows without a view count go last. `newest`: orders the kept rows by publish date, newest first. Rows without a date go last. The sort covers only the rows this call collected over the pages it walked, not the whole feed. Every collected row is returned. A call that resumes from `pagination.next_cursor` sorts its own rows and does not merge them with the earlier ones. `data.walk.sorted` states this as `scope: "collected_rows"`. (views | newest)
max_pages아니오1 to 50 (default 1, or 50 when `max_items` or `max_credits` is sent). Walk up to this many pages in one call and return the rows from all of them (after any filter). Each page walked is billed exactly as one call to this endpoint (a cached page is free) and counts against your rate limit; its charge and any refund are recorded under the page's own request id, listed in `data.walk.request_ids`. The walk stops early at the last page, or when the request's time budget runs low; `data.walk.stopped` says why (`end`, `max_pages`, `max_items`, `max_credits`, `time_budget`, `page_error`) and `pagination.next_cursor` continues from where it stopped.
max_items아니오1 to 5000. Get more in one call: keep walking pages until the response holds at least this many rows (after any filter), then stop with `data.walk.stopped: "max_items"`. The last page is returned whole (it was billed), so `data.items` can hold up to one page more than this, and `pagination.next_cursor` resumes right after it without skipping a row. Walks up to 50 pages unless `max_pages` says fewer; each page is billed as one call (a cached page is free). Add `max_credits` to cap the spend. A long walk can stop on the time budget first (`"time_budget"`): send the returned cursor with the same params to continue.
max_credits아니오1 to 100000. The most this call may spend, across every page it walks. A page starts only while the credits already spent plus that page's price (or, when higher, the most any page of this walk has cost) still fit, so the call never goes past it; the walk then stops with `data.walk.stopped: "max_credits"` and the cursor to resume. Sent alone, it walks as far as the budget goes (up to 50 pages). A value below the price of one page is a free 400 whose `error.details.page_credits` names that price. Credits a row join (`include=`) adds are known only once a page has run, so page 1 is checked against its own price.
seen아니오An id you choose (1 to 64 letters, digits, `.`, `_` or `-`). Rows your account already received under the same `seen` id are removed from the page, and the page price falls with the share of repeats: page credits x new rows / rows on the page, rounded up, so a page of nothing but repeats is free. Only the page's own price is discounted: credits for joined data (`include=`) are charged only for rows you have not received, and are never discounted. The memory lasts 24 hours from the last call that used the id, holds row ids only, and is private to your account. Use one id across a set of related searches; `data.walk.repeats` counts what was removed.
응답 예시

YouTube Search Advanced API는 무엇을 돌려주나요

모든 응답은 하나의 통합 스키마를 따라요. 크레딧을 쓰기 전에 어떤 필드가 돌아오는지, 실제 응답 본문 그대로 확인해 보세요.

응답 예시 보기
{
  "success": true,
  "platform": "youtube",
  "endpoint": "/v1/youtube/search/advanced",
  "data": {
    "items": [
      {
        "post": {
          "id": "n61ULEU7CO0",
          "url": "https://www.youtube.com/watch?v=n61ULEU7CO0",
          "content": {
            "text": "Sample comment text (redacted).",
            "media_urls": null,
            "thumbnail_url": "https://i.ytimg.com/vi/n61ULEU7CO0/hqdefault.jpg",
            "duration_seconds": null
          },
          "author": {
            "username": null,
            "display_name": "user_a34447",
            "avatar_url": null,
            "verified": null
          },
          "engagement": {
            "views": null,
            "likes": null,
            "comments": null,
            "shares": null,
            "saves": null
          },
          "flags": {
            "nsfw": null,
            "spoiler": null,
            "pinned": null,
            "deleted": false
          },
          "published_at": "2021-12-31T16:30:13.000Z",
          "ext": {
            "description": "Sample comment text (redacted). Sample comment text (redacted). Sample comment text (redacted). Sample comment text (redacted).",
            "channel_id": "UCSJ4gkVC6NrvII8umztf0Ow"
          }
        },
        "computed": {
          "engagement_rate": null,
          "language": "en",
          "content_category": "other",
          "estimated_reach": null
        }
      },
      {
        "post": {
          "id": "CFGLoQIhmow",
          "url": "https://www.youtube.com/watch?v=CFGLoQIhmow",
          "content": {
            "text": "Sample comment text (redacted).",
            "media_urls": null,
            "thumbnail_url": "https://i.ytimg.com/vi/CFGLoQIhmow/hqdefault.jpg",
            "duration_seconds": null
          },
          "author": {
            "username": null,
            "display_name": "user_a34447",
            "avatar_url": null,
            "verified": null
          },
          "engagement": {
            "views": null,
            "likes": null,
            "comments": null,
            "shares": null,
            "saves": null
          },
          "flags": {
            "nsfw": null,
            "spoiler": null,
            "pinned": null,
            "deleted": false
          },
          "published_at": "2024-10-17T19:00:07.000Z",
          "ext": {
            "description": "Sample comment text (redacted). Sample comment text (redacted). Sample comment text (redacted). Sample comment text (redacted).",
            "channel_id": "UCSJ4gkVC6NrvII8umztf0Ow"
          }
        },
        "computed": {
          "engagement_rate": null,
          "language": "en",
          "content_category": "other",
          "estimated_reach": null
        }
      }
    ],
    "next_cursor": "CAIQAA",
    "total": 1000000,
    "dropped": 0
  },
  "credits_used": 1,
  "request_id": "req_example000000",
  "cached": false,
  "pagination": {
    "next_cursor": "sc.eyJ2IjoyLCJjIjoiQ0FJUUFBIiwiZSI6InlvdXR1YmUvc2VhcmNoL2FkdmFuY2VkIiwicCI6ImN1cnNvciJ9",
    "has_more": true,
    "page_size": 2
  },
  "credits_remaining": 9999,
  "source": "captured",
  "captured_at": "2026-10-02T07:30:25.798Z",
  "redacted": true
}

통합 응답 구조를 보여 주는 실제 샘플이에요. 필드 값은 조회한 대상에 따라 달라져요.

API 상세

YouTube Search Advanced API는 어떻게 동작하나요

API 키와 함께 GET 요청을 보내면, 통합 스키마와 계산 필드를 담은 깔끔한 JSON이 돌아와요.

메서드

GET

응답 형식

JSON

왜 SocialCrawl인가요

YouTube Search Advanced 데이터는 왜 SocialCrawl로 가져올까요

YouTube 데이터 추출에서 까다로운 부분은 SocialCrawl이 가려 드려요. 통합 스키마, AI 인리치먼트, 그리고 코드에 남지 않는 플랫폼 로직까지.

개발자 우선

소셜 미디어 데이터를 몇 초 만에 수집하는 방법

개발자를 위한 가장 빠른 소셜 미디어 스크래핑 API. 월간 활성 사용자 100억 명 이상을 포괄하는 75개 플랫폼에서 프로필, 게시물, 댓글, 분석 데이터를 수집하세요.

모든 플랫폼을 하나의 스키마로

동일한 응답 구조로 75개 플랫폼을 조회하세요. 연동은 한 번이면 충분합니다.

단순 수집을 넘어 계산된 필드 제공

엔드포인트가 해당 지표를 지원하고 계산에 필요한 원본 값이 있을 때, 정규화된 레코드에 engagement_rate, estimated_reach, content_category, language를 함께 담아 바로 활용할 수 있습니다.

코드 한 줄 쓰기 전에, 데이터부터

Visual Data Explorer에 URL만 붙여넣으면 결과 카드와 정형화된 테이블, CSV 내보내기를 바로 사용할 수 있습니다.

import requests

response = requests.get(
    'https://www.socialcrawl.dev/v1/tiktok/profile',
    params={'handle': 'charlidamelio'},
    headers={'x-api-key': 'sc_YOUR_API_KEY'}
)
data = response.json()
[ .JSON ]
{
  "success": true,
  "platform": "tiktok",
  "data": {
    "author": {
      "username": "charlidamelio",
      "followers": 152400000
    },
    "engagement": {
      "likes": 12400000000,
      "engagement_rate": 0.087
    },
    "metadata": {
      "language": "en",
      "content_category": "lifestyle"
    }
  }
}
+ 75개 플랫폼
자주 묻는 질문

자주 묻는 질문

API, 요금제, 기능에 대한 질문과 답변입니다.

문의하기
YouTube 고급 영상 검색은 어떻게 하나요?
query와 원하는 필터를 GET /v1/youtube/search/advanced에 넘기면 돼요. 결과는 항상 영상이고, 영상 ID·제목·썸네일·채널·게시 시각과 함께 와요.
고급 검색은 어떤 필터를 지원하나요?
정렬 order, 길이 duration(short·medium·long), event_type(live·upcoming·completed), license, category, region, language, 그리고 published_after·published_before 기간 필터를 지원해요. includeExtras=true는 조회·좋아요·댓글 수와 재생 시간을, include=channel은 채널 구독자 수를 더해 줘요.
특정 기간에 올라온 영상만 어떻게 찾나요?
published_after와 published_before에 2026-01-01T00:00:00Z 같은 RFC-3339 시각을 넘기면 그 기간으로 결과를 좁힐 수 있어요.
기본 검색 엔드포인트와 무엇이 다른가요?
기본 /v1/youtube/search는 간단한 검색용이고, search/advanced는 전체 YouTube 필터를 열어 영상만 정밀하게 검색할 수 있게 해줘요.
고급 검색 요금은 얼마인가요?
요청당 1~11 크레딧이에요. 페이지 요금에 includeExtras=true와 include=channel이 각각 정액으로 붙고, 둘 다 쓰면 최대 10 크레딧이 더해져요. 신규 가입 시 100 크레딧이 무료로 제공되고 일별 쿼터가 없어요.

AI에게 SocialCrawl을 물어보세요

YouTube Search Advanced 데이터, 가져올 준비 되셨어요?

API 키 받고 60초 안에 YouTube 데이터를 받아 가세요.

무료로 시작하기

🤖 AI 에이전트나 LLM이신가요? 이 페이지를 markdown으로 읽어보세요