# LangChain (/docs/langchain) Wrap the SocialCrawl API in a LangChain tool so your agent can fetch current public social media data. Documented endpoint caches apply. SocialCrawl does not ship a LangChain package and does not need one. The API is a single authenticated GET request, so you wrap it in a `tool()` in about 30 lines and your agent reaches 65 platforms through that one tool. Documented endpoint caches apply. Prefer not to write the tool yourself? An MCP client gets the same access with one command, plus local validation that refuses a bad call before it costs a credit. See [Skills & MCP](/docs/skills-and-mcp.md). ## Prerequisites - Node.js and a TypeScript runner such as `tsx`. - A SocialCrawl API key from [socialcrawl.dev](https://www.socialcrawl.dev), under Dashboard → API Keys. New accounts start with 100 free credits. - A model provider key for whichever model you bind the tool to. ## How do I add social media data to a LangChain agent? ### Install the packages Check the [LangChain docs](https://docs.langchain.com/oss/javascript) for current versions. ```bash title="Terminal" npm install langchain @langchain/anthropic zod ``` ### Define one tool for the whole API Give it a zod schema that takes a `platform`, a `resource`, and the endpoint's query `params`, then call the REST API inside the tool function with your key in the `x-api-key` header. Hand the tool to `createAgent` and it runs the tool loop for you. ```typescript title="TypeScript" // socialcrawl-langchain.ts // Run with: SOCIALCRAWL_API_KEY=sc_... ANTHROPIC_API_KEY=... npx tsx socialcrawl-langchain.ts import { createAgent, tool } from "langchain"; import * as z from "zod"; const API_KEY = process.env.SOCIALCRAWL_API_KEY; if (!API_KEY) throw new Error("Set SOCIALCRAWL_API_KEY"); const socialcrawl = tool( async ({ platform, resource, params }) => { const url = new URL( `https://www.socialcrawl.dev/v1/${platform}/${resource}`, ); for (const [key, value] of Object.entries(params ?? {})) { url.searchParams.set(key, String(value)); } const res = await fetch(url, { headers: { "x-api-key": API_KEY } }); const json = await res.json(); if (!json.success) { // Hand the model a directive it can act on, not a raw error envelope. return `SocialCrawl error ${json.error.type}: ${json.error.message}. See ${json.error.doc_url}`; } // Return a string so the model can read it back as a tool message. return JSON.stringify(json.data); }, { name: "socialcrawl", description: "Fetch current public social media, commerce, and review data from SocialCrawl; documented endpoint caches apply. " + "Covers TikTok, Instagram, YouTube, LinkedIn, Reddit, Amazon and more. " + "Set `platform` (e.g. 'tiktok'), `resource` (e.g. 'profile'), and `params` " + "(the endpoint's query fields, e.g. { handle: 'charlidamelio' }).", schema: z.object({ platform: z .string() .describe("Platform slug, e.g. 'tiktok' or 'youtube'"), resource: z .string() .describe("Endpoint resource, e.g. 'profile' or 'search'"), params: z .record(z.string(), z.union([z.string(), z.number()])) .describe("Query parameters for the endpoint"), }), }, ); ``` ### Bind it to a model and run ```typescript title="TypeScript" const agent = createAgent({ model: "claude-sonnet-5", tools: [socialcrawl], }); const result = await agent.invoke({ messages: [ { role: "user", content: "How many followers does @charlidamelio have on TikTok?", }, ], }); console.log(result.messages.at(-1)?.content); ``` `createAgent` from the `langchain` package is the LangChain v1 standard. It replaced `createReactAgent` and runs the model-calls-tool-calls-model loop itself, so a query needing two rounds of tool calls still works. Swap `"claude-sonnet-5"` for any model string LangChain resolves. If you need to drive the loop by hand, `new ChatAnthropic({ model }).bindTools([socialcrawl])` still works: invoke the model, iterate `response.tool_calls`, push a `ToolMessage` per call, and invoke again until the model stops asking for tools. ## What can the tool call? Every SocialCrawl endpoint shares the same shape: a GET at `/v1/{platform}/{resource}` with query parameters and one `x-api-key` header, returning the same JSON envelope. A single tool that takes `platform`, `resource`, and `params` therefore reaches all 572 endpoints without you writing a new tool each time. | To let the agent do this | Pass | | ---------------------------------- | ---------------------------------------------------------------------- | | Read one profile, post, or listing | `platform: "tiktok"`, `resource: "profile"`, `params: { handle: ... }` | | Search one platform | `platform: "youtube"`, `resource: "search"`, `params: { query: ... }` | | Search many sources at once | `platform: "search"`, `resource: "everywhere"` | | Check the balance before it spends | `platform: "credits"`, `resource: "balance"` | Point the model at the [platform directory](/platforms) or the machine-readable [`llms.txt`](/docs/ai-agents.md) so it knows which platform and resource to pass. ## How do I keep the agent from spending too many credits? Credits are billed exactly as the REST API bills them: most endpoints are 1 credit, heavier ones 5 or 10, and composite or bundle endpoints carry their own price (`search/everywhere` is a flat 20). Cache hits cost 0 credits, and empty results and upstream errors are auto-refunded. Read `credits_remaining` from the envelope after each call to track spend, and see [Credits](/docs/credits.md) for how the ledger works. ## Troubleshooting Its description is too vague for the router. Keep the platform and resource examples in the `description` string above, and name a concrete platform in the prompt ("on TikTok") the first few times while you tune it. The loop ran out of steps. `createAgent` handles this for you; a hand-rolled `bindTools` loop must keep invoking the model until `response.tool_calls` is empty. The tool is returning the raw envelope. Check `json.success` inside the tool and return a short directive instead, as the snippet above does. See [Errors](/docs/errors.md) for what each `error.type` means. Honour the `Retry-After` response header before retrying, and back off rather than looping. See [Rate limits](/docs/rate-limits.md). Give it the catalogue. [`/llms-full.txt`](/llms-full.txt) is the complete reference, and there is one file per platform. Or use an MCP client, where the server validates the platform, endpoint, and required parameters locally before spending anything. ## Next steps - [Vercel AI SDK](/docs/vercel-ai-sdk.md): The same pattern in that framework. - [Skills & MCP](/docs/skills-and-mcp.md): Skip the DIY tool with a one-line MCP install. - [Batch endpoints](/docs/batch.md): Replace a loop of tool calls with one request. - [Authentication](/docs/authentication.md): Keys, headers, and what a 401 means.