mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-07-16 23:01:06 +02:00
Merge remote-tracking branch 'upstream/dev' into feat/instagram-scraper
This commit is contained in:
commit
e38ca19b18
119 changed files with 5948 additions and 36 deletions
|
|
@ -16,7 +16,7 @@ import type { FaqItem } from "@/lib/connectors-marketing/types";
|
|||
const canonicalUrl = "https://www.surfsense.com/mcp-server";
|
||||
|
||||
const metaDescription =
|
||||
"The SurfSense MCP server gives Claude, Cursor, and any MCP client native tools for your workspace: scrape Reddit, YouTube, Instagram, Google Maps, Google Search, and the web, plus full knowledge base access. One API key.";
|
||||
"The SurfSense MCP server gives Claude, Cursor, and any MCP client native tools for your workspace: scrape Reddit, YouTube, Instagram, TikTok, Google Maps, Google Search, and the web, plus full knowledge base access. One API key.";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "SurfSense MCP Server: Scraper APIs and Knowledge Base as Agent Tools",
|
||||
|
|
@ -95,6 +95,7 @@ const TOOL_GROUPS = [
|
|||
"surfsense_youtube_comments",
|
||||
"surfsense_instagram_scrape",
|
||||
"surfsense_instagram_details",
|
||||
"surfsense_tiktok_scrape",
|
||||
"surfsense_google_maps_scrape",
|
||||
"surfsense_google_maps_reviews",
|
||||
"surfsense_google_search",
|
||||
|
|
@ -129,7 +130,7 @@ const FAQ: FaqItem[] = [
|
|||
{
|
||||
question: "What is the SurfSense MCP server?",
|
||||
answer:
|
||||
"It is a Model Context Protocol server that exposes your SurfSense workspace to MCP clients like Claude Code, Cursor, and Claude Desktop. Your agents get native tools for every scraper API (Reddit, YouTube, Instagram, Google Maps, Google Search, web crawl) and for searching, reading, and writing your knowledge base.",
|
||||
"It is a Model Context Protocol server that exposes your SurfSense workspace to MCP clients like Claude Code, Cursor, and Claude Desktop. Your agents get native tools for every scraper API (Reddit, YouTube, Instagram, TikTok, Google Maps, Google Search, web crawl) and for searching, reading, and writing your knowledge base.",
|
||||
},
|
||||
{
|
||||
question: "Which MCP clients does it work with?",
|
||||
|
|
@ -217,8 +218,9 @@ export default function McpServerPage() {
|
|||
</h1>
|
||||
<p className="mt-5 max-w-xl text-base leading-relaxed text-muted-foreground sm:text-lg">
|
||||
The SurfSense MCP server hands Claude, Cursor, or any MCP client the whole platform:
|
||||
scrape Reddit, YouTube, Instagram, Google Maps, Google Search, and the open web, and
|
||||
search, read, and write your knowledge base. One API key, typed tools, pay as you go.
|
||||
scrape Reddit, YouTube, Instagram, TikTok, Google Maps, Google Search, and the open
|
||||
web, and search, read, and write your knowledge base. One API key, typed tools, pay
|
||||
as you go.
|
||||
</p>
|
||||
<div className="mt-8 flex flex-wrap items-center gap-3">
|
||||
<Button asChild size="lg">
|
||||
|
|
@ -403,6 +405,9 @@ export default function McpServerPage() {
|
|||
<Button asChild variant="ghost" size="sm">
|
||||
<Link href="/instagram">Instagram API</Link>
|
||||
</Button>
|
||||
<Button asChild variant="ghost" size="sm">
|
||||
<Link href="/tiktok">TikTok API</Link>
|
||||
</Button>
|
||||
<Button asChild variant="ghost" size="sm">
|
||||
<Link href="/google-maps">Google Maps API</Link>
|
||||
</Button>
|
||||
|
|
|
|||
|
|
@ -719,7 +719,7 @@ export function HeroSection() {
|
|||
>
|
||||
SurfSense is an open-source competitive intelligence platform. Your AI agents monitor
|
||||
competitors, track rankings, and listen to your market with live data from platforms
|
||||
like Reddit, Instagram, YouTube, Google Maps, Google Search, and the open web.
|
||||
like Reddit, YouTube, Instagram, TikTok, Google Maps, Google Search, and the open web.
|
||||
</p>
|
||||
|
||||
<div className="relative mb-4 flex w-full flex-col justify-center gap-y-2 sm:flex-row sm:justify-start sm:space-y-0 sm:space-x-4">
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ const PATHS: {
|
|||
eyebrow: "For developers & agents",
|
||||
title: "The whole platform is programmable",
|
||||
description:
|
||||
"Everything SurfSense agents can do is a typed REST API: scrape Reddit, YouTube, Google Maps, Google Search, and the open web, search the knowledge base, run automations. One key, JSON in and out, $5 free credit, pay as you go. Already running agents in Claude, Cursor, or your own harness? The SurfSense MCP server hands them the same tools natively.",
|
||||
"Everything SurfSense agents can do is a typed REST API: scrape Reddit, YouTube, TikTok, Google Maps, Google Search, and the open web, search the knowledge base, run automations. One key, JSON in and out, $5 free credit, pay as you go. Already running agents in Claude, Cursor, or your own harness? The SurfSense MCP server hands them the same tools natively.",
|
||||
links: [
|
||||
{ label: "Read the docs", href: "/docs" },
|
||||
{ label: "SurfSense MCP server", href: "/mcp-server" },
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ const demoPlans = [
|
|||
billingText: "Your first $5 of credit is free. No subscription, ever",
|
||||
features: [
|
||||
"$5 of free credit to start, one balance for everything",
|
||||
"Platform connectors: Reddit, YouTube, Google Maps, Google Search, and the open web",
|
||||
"Platform connectors: Reddit, YouTube, TikTok, Google Maps, Google Search, and the open web",
|
||||
"Call every connector as a REST API with your key or through the MCP server",
|
||||
"Pay per item returned and per page crawled. Failed calls are never billed",
|
||||
"Premium models like GPT-5.5, Claude Sonnet 5, Gemini 3.1 Pro billed at provider cost",
|
||||
|
|
@ -95,7 +95,7 @@ const faqData: FAQSection[] = [
|
|||
{
|
||||
question: "How does Pay As You Go work?",
|
||||
answer:
|
||||
"There is no monthly subscription. Start with $5 of free credit, and when you need more, add any amount. $1 buys exactly $1 of credit, added to your balance immediately. You can enable automatic refills when your balance runs low, and turn them off any time."
|
||||
"There is no monthly subscription. Start with $5 of free credit, and when you need more, add any amount. $1 buys exactly $1 of credit, added to your balance immediately. You can enable automatic refills when your balance runs low, and turn them off any time.",
|
||||
},
|
||||
{
|
||||
question: "What happens if I run out of credit?",
|
||||
|
|
|
|||
|
|
@ -76,11 +76,11 @@ export function SoftwareApplicationJsonLd() {
|
|||
"Free self-hosted from the open-source repo; cloud starts with $5 of free credit, then pay as you go",
|
||||
},
|
||||
description:
|
||||
"SurfSense is an open-source competitive intelligence platform. AI agents monitor competitors, track rankings, and listen to your market with platform-native connectors for Reddit, YouTube, Google Maps, Google Search, and the open web, through one API or MCP server.",
|
||||
"SurfSense is an open-source competitive intelligence platform. AI agents monitor competitors, track rankings, and listen to your market with platform-native connectors for Reddit, YouTube, TikTok, Google Maps, Google Search, and the open web, through one API or MCP server.",
|
||||
url: "https://www.surfsense.com",
|
||||
downloadUrl: "https://github.com/MODSetter/SurfSense/releases",
|
||||
featureList: [
|
||||
"Platform-native connectors: Reddit, YouTube, Google Maps, Google Search, Web Crawl",
|
||||
"Platform-native connectors: Reddit, YouTube, TikTok, Google Maps, Google Search, Web Crawl",
|
||||
"MCP server that exposes every connector as a native agent tool",
|
||||
"Agent harness with retries, structured output, and credit metering",
|
||||
"Competitor, brand, and rank monitoring with briefs and alerts",
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ Connectors bring data into SurfSense — either as searchable knowledge or as li
|
|||
<Card
|
||||
icon={<Zap />}
|
||||
title="Native Connectors"
|
||||
description="SurfSense's built-in scraper APIs: Reddit, YouTube, Instagram, Google Maps, Google Search, and Web Crawl — usable in chat, the API Playground, or via REST"
|
||||
description="SurfSense's built-in scraper APIs: Reddit, YouTube, Instagram, TikTok, Google Maps, Google Search, and Web Crawl — usable in chat, the API Playground, or via REST"
|
||||
href="/docs/connectors/native"
|
||||
/>
|
||||
<Card
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
title: Native Connectors
|
||||
description: SurfSense's built-in scraper APIs for Reddit, YouTube, Instagram, Google Maps, Google Search, and the web
|
||||
description: SurfSense's built-in scraper APIs for Reddit, YouTube, Instagram, TikTok, Google Maps, Google Search, and the web
|
||||
---
|
||||
|
||||
import { Card, Cards } from 'fumadocs-ui/components/card';
|
||||
|
|
@ -23,6 +23,11 @@ Native connectors are SurfSense's own scraper APIs — built into the platform,
|
|||
description="Posts, reels, comments, and profile, hashtag, and place details"
|
||||
href="/docs/connectors/native/instagram"
|
||||
/>
|
||||
<Card
|
||||
title="TikTok"
|
||||
description="Videos by URL, profile, hashtag, or search"
|
||||
href="/docs/connectors/native/tiktok"
|
||||
/>
|
||||
<Card
|
||||
title="Google Maps"
|
||||
description="Places with details, ratings, photos, and reviews"
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"title": "Native Connectors",
|
||||
"pages": ["reddit", "youtube", "instagram", "google-maps", "google-search", "web-crawl"],
|
||||
"pages": ["reddit", "youtube", "instagram", "tiktok", "google-maps", "google-search", "web-crawl"],
|
||||
"defaultOpen": false
|
||||
}
|
||||
|
|
|
|||
97
surfsense_web/content/docs/connectors/native/tiktok.mdx
Normal file
97
surfsense_web/content/docs/connectors/native/tiktok.mdx
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
---
|
||||
title: TikTok
|
||||
description: Scrape public TikTok videos, comments, accounts, and trending feeds
|
||||
---
|
||||
|
||||
The TikTok connector pulls structured public data from TikTok across four verbs: **scrape** (videos), **comments**, **user search** (accounts), and **trending**. Every verb returns `{ "items": [...] }` and is billed per returned item; surfaced errors (an `errorCode` field, e.g. a withheld feed) are never charged.
|
||||
|
||||
## Scrape videos
|
||||
|
||||
```bash
|
||||
POST /api/v1/workspaces/{workspace_id}/scrapers/tiktok/scrape
|
||||
```
|
||||
|
||||
Give it URLs (a video, a profile, a hashtag, or a search page) and/or profiles, hashtags, or search terms; returns videos (caption, author, play/like/comment/share counts, music, hashtags, timestamps, and the web URL). At least one of `urls`, `profiles`, `hashtags`, or `search_queries` is required.
|
||||
|
||||
| Field | Default | Description |
|
||||
|-------|---------|-------------|
|
||||
| `urls` | — | TikTok URLs: a video, a profile (`/@<user>`), a hashtag (`/tag/<name>`), or a search URL (max 20 sources per call) |
|
||||
| `profiles` | — | Profile usernames, with or without a leading `@` |
|
||||
| `hashtags` | — | Hashtag names, without the `#` |
|
||||
| `search_queries` | — | Search terms to run on TikTok |
|
||||
| `results_per_page` | `10` | Max videos per profile/hashtag/search target |
|
||||
| `max_items` | `10` | Max total videos returned across all sources (hard cap 100) |
|
||||
|
||||
```bash
|
||||
curl -X POST "$BASE_URL/api/v1/workspaces/1/scrapers/tiktok/scrape" \
|
||||
-H "Authorization: Bearer $SURFSENSE_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{ "hashtags": ["food"], "max_items": 25 }'
|
||||
```
|
||||
|
||||
<Callout type="info">
|
||||
Video and hashtag targets are the reliable video paths. A `profiles` target returns the account's **metadata** (name, followers, bio, verification) reliably, but TikTok often withholds its **video list** from automated clients — so a profile can return metadata with no videos. Keyword **video** search is login-walled and returns a surfaced error; to find accounts by keyword use **user search** below.
|
||||
</Callout>
|
||||
|
||||
## Comments
|
||||
|
||||
```bash
|
||||
POST /api/v1/workspaces/{workspace_id}/scrapers/tiktok/comments
|
||||
```
|
||||
|
||||
Given TikTok video URLs, returns each video's public comment thread: comment text, author, like count, and reply count (replies carry `repliesToId`, the parent comment id).
|
||||
|
||||
| Field | Default | Description |
|
||||
|-------|---------|-------------|
|
||||
| `video_urls` | — | TikTok video URLs (`/@<user>/video/<id>`), max 20 per call |
|
||||
| `comments_per_video` | `20` | Max comments per video |
|
||||
| `max_items` | `20` | Max total comments returned (hard cap 100) |
|
||||
|
||||
```bash
|
||||
curl -X POST "$BASE_URL/api/v1/workspaces/1/scrapers/tiktok/comments" \
|
||||
-H "Authorization: Bearer $SURFSENSE_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{ "video_urls": ["https://www.tiktok.com/@nasa/video/123"], "max_items": 50 }'
|
||||
```
|
||||
|
||||
## User search
|
||||
|
||||
```bash
|
||||
POST /api/v1/workspaces/{workspace_id}/scrapers/tiktok/user_search
|
||||
```
|
||||
|
||||
Finds public TikTok accounts by keyword — the reliable account-discovery path. Returns matching profiles with name, followers, bio, and verification.
|
||||
|
||||
| Field | Default | Description |
|
||||
|-------|---------|-------------|
|
||||
| `queries` | — | Keywords to find accounts by, e.g. `["nasa", "cooking"]` (max 20) |
|
||||
| `results_per_query` | `10` | Max accounts per query |
|
||||
| `max_items` | `10` | Max total accounts returned (hard cap 100) |
|
||||
|
||||
```bash
|
||||
curl -X POST "$BASE_URL/api/v1/workspaces/1/scrapers/tiktok/user_search" \
|
||||
-H "Authorization: Bearer $SURFSENSE_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{ "queries": ["space agency"], "max_items": 20 }'
|
||||
```
|
||||
|
||||
## Trending
|
||||
|
||||
```bash
|
||||
POST /api/v1/workspaces/{workspace_id}/scrapers/tiktok/trending
|
||||
```
|
||||
|
||||
Returns the current trending videos from TikTok's Explore feed — no input needed beyond how many to return. Items use the same video shape as **scrape** and bill on the same per-video meter.
|
||||
|
||||
| Field | Default | Description |
|
||||
|-------|---------|-------------|
|
||||
| `max_items` | `20` | Max trending videos returned (hard cap 100) |
|
||||
|
||||
```bash
|
||||
curl -X POST "$BASE_URL/api/v1/workspaces/1/scrapers/tiktok/trending" \
|
||||
-H "Authorization: Bearer $SURFSENSE_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{ "max_items": 30 }'
|
||||
```
|
||||
|
||||
For the full input and output JSON schemas and generated code snippets in your language, open **API Playground → TikTok** in your workspace.
|
||||
|
|
@ -7,7 +7,7 @@ import { Tab, Tabs } from 'fumadocs-ui/components/tabs';
|
|||
|
||||
# SurfSense MCP Server
|
||||
|
||||
The SurfSense MCP server exposes your workspace to any [Model Context Protocol](https://modelcontextprotocol.io/) client. Your agent gets 21 native, typed tools: every scraper (Reddit, YouTube, Instagram, Google Maps, Google Search, web crawl), full knowledge-base access (search, read, add, upload, update, delete), and a workspace selector.
|
||||
The SurfSense MCP server exposes your workspace to any [Model Context Protocol](https://modelcontextprotocol.io/) client. Your agent gets 21 native, typed tools: every scraper (Reddit, YouTube, Instagram, TikTok, Google Maps, Google Search, web crawl), full knowledge-base access (search, read, add, upload, update, delete), and a workspace selector.
|
||||
|
||||
Connect it two ways: the **hosted** server at `https://mcp.surfsense.com/mcp` (nothing to install — just an API key), or run it yourself over **stdio** against any SurfSense backend, cloud or self-hosted.
|
||||
|
||||
|
|
@ -264,7 +264,7 @@ For self-host (stdio), all settings are environment variables passed by the clie
|
|||
| Group | Tools |
|
||||
|-------|-------|
|
||||
| Workspaces | `surfsense_list_workspaces`, `surfsense_select_workspace` |
|
||||
| Scrapers | `surfsense_reddit_scrape`, `surfsense_youtube_scrape`, `surfsense_youtube_comments`, `surfsense_instagram_scrape`, `surfsense_instagram_details`, `surfsense_google_maps_scrape`, `surfsense_google_maps_reviews`, `surfsense_google_search`, `surfsense_web_crawl`, `surfsense_list_scraper_runs`, `surfsense_get_scraper_run` |
|
||||
| Scrapers | `surfsense_reddit_scrape`, `surfsense_youtube_scrape`, `surfsense_youtube_comments`, `surfsense_instagram_scrape`, `surfsense_instagram_details`, `surfsense_tiktok_scrape`, `surfsense_google_maps_scrape`, `surfsense_google_maps_reviews`, `surfsense_google_search`, `surfsense_web_crawl`, `surfsense_list_scraper_runs`, `surfsense_get_scraper_run` |
|
||||
| Knowledge base | `surfsense_search_knowledge_base`, `surfsense_list_documents`, `surfsense_get_document`, `surfsense_add_document`, `surfsense_upload_file`, `surfsense_update_document`, `surfsense_delete_document` |
|
||||
|
||||
Usage is billed exactly like the REST API — scraper tools are metered per returned item, and every call is recorded under **API Playground → Runs**.
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import { googleMaps } from "./google-maps";
|
|||
import { googleSearch } from "./google-search";
|
||||
import { instagram } from "./instagram";
|
||||
import { reddit } from "./reddit";
|
||||
import { tiktok } from "./tiktok";
|
||||
import type { ConnectorPageContent } from "./types";
|
||||
import { webCrawl } from "./web-crawl";
|
||||
import { youtube } from "./youtube";
|
||||
|
|
@ -13,6 +14,7 @@ const CONNECTOR_LIST: ConnectorPageContent[] = [
|
|||
reddit,
|
||||
youtube,
|
||||
instagram,
|
||||
tiktok,
|
||||
googleMaps,
|
||||
googleSearch,
|
||||
webCrawl,
|
||||
|
|
|
|||
|
|
@ -311,10 +311,10 @@ export const reddit: ConnectorPageContent = {
|
|||
related: [
|
||||
{ label: "YouTube API", href: "/youtube" },
|
||||
{ label: "Instagram API", href: "/instagram" },
|
||||
{ label: "TikTok API", href: "/tiktok" },
|
||||
{ label: "Google Maps API", href: "/google-maps" },
|
||||
{ label: "SERP API", href: "/google-search" },
|
||||
{ label: "Web Crawl API", href: "/web-crawl" },
|
||||
{ label: "SurfSense MCP Server", href: "/mcp-server" },
|
||||
{ label: "Read the docs", href: "/docs" },
|
||||
],
|
||||
};
|
||||
|
|
|
|||
285
surfsense_web/lib/connectors-marketing/tiktok.tsx
Normal file
285
surfsense_web/lib/connectors-marketing/tiktok.tsx
Normal file
|
|
@ -0,0 +1,285 @@
|
|||
import { IconBrandTiktok } from "@tabler/icons-react";
|
||||
import type { ConnectorPageContent } from "./types";
|
||||
|
||||
export const tiktok: ConnectorPageContent = {
|
||||
slug: "tiktok",
|
||||
name: "TikTok",
|
||||
icon: IconBrandTiktok,
|
||||
|
||||
metaTitle: "TikTok Scraper API for Trend and Creator Research | SurfSense",
|
||||
metaDescription:
|
||||
"Scrape public TikTok videos, comments, accounts, and trending feeds by hashtag, profile, or URL with the SurfSense TikTok Scraper API. No approval process or research-API gatekeeping, plus a free tier. Start now.",
|
||||
keywords: [
|
||||
"tiktok scraper",
|
||||
"tiktok scraper api",
|
||||
"tiktok api",
|
||||
"tiktok api alternative",
|
||||
"scrape tiktok",
|
||||
"tiktok data api",
|
||||
"tiktok hashtag scraper",
|
||||
"tiktok comments scraper",
|
||||
"tiktok trending scraper",
|
||||
"tiktok user search",
|
||||
"tiktok trend tracking",
|
||||
"tiktok mcp",
|
||||
"social listening",
|
||||
"influencer research tool",
|
||||
"short-form video analytics",
|
||||
],
|
||||
|
||||
h1: "TikTok Scraper API for Trend and Creator Research",
|
||||
heroLede:
|
||||
"The SurfSense TikTok API extracts public videos by hashtag, creator profile, or URL without TikTok's approval-gated Research API. Give your AI agents a live feed of what your market watches and shares, so you catch a trend while it is still rising.",
|
||||
|
||||
transcript: {
|
||||
prompt: "Find trending TikToks about meal prep this week",
|
||||
toolCall: 'tiktok.scrape({ hashtags: ["mealprep"], max_items: 25 })',
|
||||
rows: [
|
||||
{
|
||||
primary: "5 high-protein lunches under 400 cals",
|
||||
secondary: "@fitmeals · 2.1M plays · 184K likes",
|
||||
tag: "breakout",
|
||||
},
|
||||
{
|
||||
primary: "The $20 weekly meal prep everyone's copying",
|
||||
secondary: "@budgetbites · 980K plays · 72K likes",
|
||||
tag: "rising",
|
||||
},
|
||||
{
|
||||
primary: "POV: your fridge after Sunday meal prep",
|
||||
secondary: "@cleaneats · 640K plays · 51K likes",
|
||||
tag: "high engagement",
|
||||
},
|
||||
],
|
||||
resultSummary: "25 videos · 8.4M plays · surfaced in 3.2s",
|
||||
},
|
||||
|
||||
extractIntro:
|
||||
"Every call returns structured items. Scrape videos from a hashtag, creator profile, or video URL — or switch verbs to pull a video's comments, discover accounts by keyword, or fetch the current trending feed.",
|
||||
extractFields: [
|
||||
{
|
||||
label: "Videos",
|
||||
description: "Caption text, canonical web URL, duration, and cover image for each video.",
|
||||
},
|
||||
{
|
||||
label: "Engagement",
|
||||
description:
|
||||
"Play, like, comment, share, and save counts — the signal for what is breaking out.",
|
||||
},
|
||||
{
|
||||
label: "Authors",
|
||||
description: "Creator handle, nickname, follower and heart counts, and verified status.",
|
||||
},
|
||||
{
|
||||
label: "Music",
|
||||
description: "Track name, artist, and whether the sound is original — the seed of a trend.",
|
||||
},
|
||||
{
|
||||
label: "Hashtags",
|
||||
description: "Every hashtag on a video, so you can map a topic cluster or campaign.",
|
||||
},
|
||||
{
|
||||
label: "Timestamps",
|
||||
description: "Created and scraped times so you can track a video's momentum over runs.",
|
||||
},
|
||||
],
|
||||
|
||||
useCasesHeading: "What teams do with the TikTok API",
|
||||
useCases: [
|
||||
{
|
||||
title: "Trend and hashtag monitoring",
|
||||
description:
|
||||
"Track a hashtag and feed the stream to an agent that flags breakout videos, rising sounds, and formats before they saturate. Catch the wave while it is still rising, not after.",
|
||||
},
|
||||
{
|
||||
title: "Creator and influencer discovery",
|
||||
description:
|
||||
"Surface the creators driving a topic, ranked by real engagement, so your team shortlists partners from data instead of a manager's pitch deck.",
|
||||
},
|
||||
{
|
||||
title: "Competitor content analysis",
|
||||
description:
|
||||
"Watch what your category posts and what actually lands. Turn a competitor's best-performing formats and hooks into your own content brief.",
|
||||
},
|
||||
{
|
||||
title: "Campaign and sentiment tracking",
|
||||
description:
|
||||
"Measure how a launch or branded hashtag spreads across TikTok — video count, reach, and engagement over time — then pull the comments on top videos to read how the audience actually reacts, not just a vanity view count.",
|
||||
},
|
||||
],
|
||||
|
||||
comparison: {
|
||||
heading: "A TikTok API alternative built for agents",
|
||||
intro:
|
||||
"TikTok's official Research API is approval-gated and largely limited to academic and nonprofit use. If you cannot get access or need it for commercial research, here is how SurfSense compares.",
|
||||
columnLabel: "Official TikTok API",
|
||||
rows: [
|
||||
{
|
||||
feature: "Access",
|
||||
official: "Application and approval, often restricted to academic/nonprofit use",
|
||||
surfsense: "One API key, no approval process",
|
||||
},
|
||||
{
|
||||
feature: "Pricing",
|
||||
official: "Free but gated, with usage quotas per approved project",
|
||||
surfsense: "Pay per item returned, with a free tier to start",
|
||||
},
|
||||
{
|
||||
feature: "Signing",
|
||||
official: "You manage the client-side signature that TikTok rotates",
|
||||
surfsense: "Handled for you; a real browser signs each request",
|
||||
},
|
||||
{
|
||||
feature: "Setup",
|
||||
official: "Register a developer app and await review",
|
||||
surfsense: "One API key, or add the MCP server to your agent",
|
||||
},
|
||||
{
|
||||
feature: "Agent-ready",
|
||||
official: "No; you build the harness yourself",
|
||||
surfsense: "MCP server exposes scrape, comments, user search, and trending as native tools",
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
api: {
|
||||
platform: "tiktok",
|
||||
verb: "scrape",
|
||||
mcpTool: "tiktok.scrape",
|
||||
requestBody: {
|
||||
hashtags: ["mealprep"],
|
||||
max_items: 25,
|
||||
},
|
||||
},
|
||||
|
||||
schema: {
|
||||
requestNote:
|
||||
"Provide at least one source: urls, profiles, hashtags, or search_queries. Up to 20 sources per call.",
|
||||
request: [
|
||||
{
|
||||
name: "urls",
|
||||
type: "string[]",
|
||||
defaultValue: "[]",
|
||||
description:
|
||||
"TikTok URLs to scrape: a video, a profile (/@user), or a hashtag (/tag/name). Max 20.",
|
||||
},
|
||||
{
|
||||
name: "profiles",
|
||||
type: "string[]",
|
||||
defaultValue: "[]",
|
||||
description: "Profile usernames to scrape, with or without a leading @. Max 20.",
|
||||
},
|
||||
{
|
||||
name: "hashtags",
|
||||
type: "string[]",
|
||||
defaultValue: "[]",
|
||||
description: "Hashtag names to scrape, without the # prefix. Max 20.",
|
||||
},
|
||||
{
|
||||
name: "search_queries",
|
||||
type: "string[]",
|
||||
defaultValue: "[]",
|
||||
description:
|
||||
"Keyword search terms. Keyword video search is login-walled and returns no videos — use hashtags/profiles/urls for videos, or user_search for accounts. Max 20.",
|
||||
},
|
||||
{
|
||||
name: "results_per_page",
|
||||
type: "integer",
|
||||
defaultValue: "10",
|
||||
description: "Max videos to pull per profile or hashtag target. 1 to 100.",
|
||||
},
|
||||
{
|
||||
name: "max_items",
|
||||
type: "integer",
|
||||
defaultValue: "10",
|
||||
description: "Max total videos to return across all sources. 1 to 100.",
|
||||
},
|
||||
],
|
||||
responseNote:
|
||||
"The response is { items: [...] } with one video item per result. One returned item is one billable unit.",
|
||||
response: [
|
||||
{
|
||||
name: "id / webVideoUrl",
|
||||
type: "string",
|
||||
description: "The TikTok video ID and its canonical web URL.",
|
||||
},
|
||||
{
|
||||
name: "text",
|
||||
type: "string",
|
||||
description: "The video caption, including inline hashtags and mentions.",
|
||||
},
|
||||
{
|
||||
name: "authorMeta",
|
||||
type: "object",
|
||||
description: "Creator handle, nickname, follower and heart counts, and verified flag.",
|
||||
},
|
||||
{
|
||||
name: "musicMeta",
|
||||
type: "object",
|
||||
description: "Track name, artist, and whether the sound is original.",
|
||||
},
|
||||
{
|
||||
name: "videoMeta",
|
||||
type: "object",
|
||||
description: "Duration, dimensions, and cover image for the video.",
|
||||
},
|
||||
{
|
||||
name: "playCount / diggCount",
|
||||
type: "integer",
|
||||
description: "Play count and like (digg) count, the core reach and engagement signals.",
|
||||
},
|
||||
{
|
||||
name: "commentCount / shareCount",
|
||||
type: "integer",
|
||||
description: "Comment and share counts for measuring conversation and spread.",
|
||||
},
|
||||
{
|
||||
name: "hashtags",
|
||||
type: "object[]",
|
||||
description: "The hashtags attached to the video, for topic and campaign mapping.",
|
||||
},
|
||||
{
|
||||
name: "createTimeISO / scrapedAt",
|
||||
type: "string",
|
||||
description: "ISO timestamps for when the video was posted and when it was scraped.",
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
faq: [
|
||||
{
|
||||
question: "Is scraping TikTok legal?",
|
||||
answer:
|
||||
"SurfSense reads only public TikTok data, the same videos any logged-out visitor can see. It never logs in and cannot access private or deleted content. As always, review TikTok's terms and your own compliance needs before you run at scale.",
|
||||
},
|
||||
{
|
||||
question: "Does this need the official TikTok API?",
|
||||
answer:
|
||||
"No. It is an independent alternative, not a wrapper on the Research API, so there is no application or approval process. You call the SurfSense API with one key, or add the MCP server to your agent, and get structured videos back.",
|
||||
},
|
||||
{
|
||||
question: "What are the rate limits?",
|
||||
answer:
|
||||
"Each call caps at 100 returned videos across all sources, with up to 20 hashtags, profiles, or URLs per request. SurfSense manages the underlying request budget and request signing for you.",
|
||||
},
|
||||
{
|
||||
question: "Can I scrape a specific creator's videos?",
|
||||
answer:
|
||||
"Pass a profile or profile URL and you always get the account's metadata — name, followers, bio, verification. TikTok often withholds the profile video list from automated clients, so that list can come back empty even for a public account; for reliable video results, scrape by hashtag or by a direct video URL.",
|
||||
},
|
||||
{
|
||||
question: "What TikTok data can I scrape?",
|
||||
answer:
|
||||
"Four verbs: scrape (videos by hashtag, profile, or URL), comments (a video's public comment thread), user search (find accounts by keyword — the reliable discovery path, since keyword video search is login-walled), and trending (the current Explore feed). Each returns structured items and is billed per item returned.",
|
||||
},
|
||||
],
|
||||
|
||||
related: [
|
||||
{ label: "Reddit API", href: "/reddit" },
|
||||
{ label: "YouTube API", href: "/youtube" },
|
||||
{ label: "Google Maps API", href: "/google-maps" },
|
||||
{ label: "SERP API", href: "/google-search" },
|
||||
{ label: "Web Crawl API", href: "/web-crawl" },
|
||||
{ label: "SurfSense MCP Server", href: "/mcp-server" },
|
||||
],
|
||||
};
|
||||
|
|
@ -271,10 +271,10 @@ export const youtube: ConnectorPageContent = {
|
|||
related: [
|
||||
{ label: "Reddit API", href: "/reddit" },
|
||||
{ label: "Instagram API", href: "/instagram" },
|
||||
{ label: "TikTok API", href: "/tiktok" },
|
||||
{ label: "Google Maps API", href: "/google-maps" },
|
||||
{ label: "SERP API", href: "/google-search" },
|
||||
{ label: "Web Crawl API", href: "/web-crawl" },
|
||||
{ label: "SurfSense MCP Server", href: "/mcp-server" },
|
||||
{ label: "Read the docs", href: "/docs" },
|
||||
],
|
||||
};
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import {
|
|||
GoogleSearchIcon,
|
||||
InstagramIcon,
|
||||
RedditIcon,
|
||||
TikTokIcon,
|
||||
WebIcon,
|
||||
YouTubeIcon,
|
||||
} from "./platform-icons";
|
||||
|
|
@ -58,6 +59,21 @@ export const PLAYGROUND_PLATFORMS: PlaygroundPlatform[] = [
|
|||
{ name: "instagram.details", verb: "details", label: "Details" },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "tiktok",
|
||||
label: "TikTok",
|
||||
icon: TikTokIcon,
|
||||
verbs: [
|
||||
{ name: "tiktok.scrape", verb: "scrape", label: "Scrape" },
|
||||
{ name: "tiktok.comments", verb: "comments", label: "Comments" },
|
||||
{
|
||||
name: "tiktok.user_search",
|
||||
verb: "user_search",
|
||||
label: "User Search",
|
||||
},
|
||||
{ name: "tiktok.trending", verb: "trending", label: "Trending" },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "google_maps",
|
||||
label: "Google Maps",
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ function brandIcon(src: string, alt: string) {
|
|||
export const RedditIcon = brandIcon("/connectors/reddit.svg", "Reddit");
|
||||
export const YouTubeIcon = brandIcon("/connectors/youtube.svg", "YouTube");
|
||||
export const InstagramIcon = brandIcon("/connectors/instagram.svg", "Instagram");
|
||||
export const TikTokIcon = brandIcon("/connectors/tiktok.svg", "TikTok");
|
||||
export const GoogleMapsIcon = brandIcon("/connectors/google-maps.svg", "Google Maps");
|
||||
export const GoogleSearchIcon = brandIcon("/connectors/google-search.svg", "Google Search");
|
||||
export const WebIcon = brandIcon("/connectors/web.svg", "Web");
|
||||
|
|
|
|||
6
surfsense_web/public/connectors/tiktok.svg
Normal file
6
surfsense_web/public/connectors/tiktok.svg
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="48" height="48">
|
||||
<path fill="#212121" fill-rule="evenodd" d="M10.904,6h26.191C39.804,6,42,8.196,42,10.909v26.191C42,39.804,39.804,42,37.096,42H10.904C8.196,42,6,39.804,6,37.091V10.909C6,8.196,8.196,6,10.904,6z" clip-rule="evenodd"/>
|
||||
<path fill="#ec407a" fill-rule="evenodd" d="M29.208,20.607c1.576,1.126,3.507,1.788,5.592,1.788v-4.011c-0.395,0-0.788-0.041-1.174-0.123v3.157c-2.085,0-4.015-0.663-5.592-1.788v8.184c0,4.094-3.321,7.413-7.417,7.413c-1.528,0-2.949-0.462-4.129-1.254c1.347,1.376,3.225,2.23,5.303,2.23c4.096,0,7.417-3.319,7.417-7.413L29.208,20.607L29.208,20.607z M30.657,16.561c-0.805-0.879-1.334-2.016-1.449-3.273v-0.516h-1.113C28.375,14.369,29.331,15.734,30.657,16.561L30.657,16.561z M19.079,30.832c-0.45-0.59-0.693-1.311-0.692-2.053c0-1.873,1.519-3.391,3.393-3.391c0.349,0,0.696,0.053,1.029,0.159v-4.1c-0.389-0.053-0.781-0.076-1.174-0.068v3.191c-0.333-0.106-0.68-0.16-1.03-0.159c-1.874,0-3.392,1.518-3.392,3.392C17.213,29.156,17.972,30.31,19.079,30.832z" clip-rule="evenodd"/>
|
||||
<path fill="#fff" fill-rule="evenodd" d="M28.034,19.63c1.576,1.126,3.507,1.788,5.592,1.788v-3.157c-1.164-0.248-2.194-0.856-2.969-1.701c-1.326-0.827-2.282-2.191-2.561-3.789h-2.923v16.018c-0.007,1.867-1.523,3.379-3.393,3.379c-1.102,0-2.081-0.525-2.701-1.338c-1.107-0.522-1.866-1.678-1.866-3.011c0-1.874,1.518-3.392,3.392-3.392c0.359,0,0.705,0.056,1.03,0.159v-3.191c-4.024,0.083-7.26,3.369-7.26,7.411c0,2.018,0.806,3.847,2.114,5.183c1.18,0.792,2.601,1.254,4.129,1.254c4.096,0,7.417-3.319,7.417-7.413L28.034,19.63z" clip-rule="evenodd"/>
|
||||
<path fill="#81ecec" fill-rule="evenodd" d="M33.626,18.261v-0.854c-1.05,0.002-2.078-0.292-2.969-0.848C31.445,17.423,32.483,18.018,33.626,18.261z M28.095,12.771c-0.027-0.153-0.047-0.306-0.061-0.461v-0.516h-4.036v16.019c-0.006,1.867-1.522,3.379-3.393,3.379c-0.549,0-1.068-0.13-1.527-0.362c0.62,0.813,1.599,1.338,2.701,1.338c1.87,0,3.386-1.512,3.393-3.379V12.771H28.095z M21.35,21.657v-0.909c-0.337-0.046-0.677-0.069-1.017-0.069c-4.097,0-7.418,3.319-7.418,7.413c0,2.567,1.305,4.829,3.289,6.159c-1.308-1.336-2.114-3.165-2.114-5.183C14.09,25.026,17.326,21.74,21.35,21.657z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.1 KiB |
Loading…
Add table
Add a link
Reference in a new issue