Tiktok Trend Radar
by @nicemaths123
Automatically monitors TikTok and Instagram trends, detects hashtag spikes, generates AI-driven content ideas and scripts, and produces short videos via InVi...
clawhub install tiktok-trendπ About This Skill
Automated TikTok & Instagram Trend Radar Skill
Overview
This skill builds a fully automated trend monitoring pipeline that: 1. Scrapes TikTok and Instagram in real-time using Apify 2. Sends trend data into Claude (via OpenClaw) for AI analysis 3. Automatically generates content ideas, video scripts, and hashtag explosion alerts 4. Produces ready-to-publish short videos via InVideo AI
The result: you know what's trending *before* everyone else β and you already have the content ready.
> π Apify: https://www.apify.com/?fpr=dx06p > π InVideo: https://invideo.sjv.io/TBB
What This Skill Does
Architecture Overview
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β TREND RADAR PIPELINE β
β β
β ββββββββββββ ββββββββββββ ββββββββββββββββββββββββ β
β β Apify βββββΆβ Trend βββββΆβ Claude / OpenClaw β β
β β Scraper β β Detector β β AI Analysis Engine β β
β βTikTok + β β(spike β β β β
β βInstagram β βdetection)β β β’ Content ideas β β
β ββββββββββββ ββββββββββββ β β’ Script generation β β
β β β’ Hashtag insights β β
β ββββββββββββ¬ββββββββββββ β
β β β
β βββββββββββββββββββββΌβββββββββββββ β
β β InVideo AI β β
β β Auto Video Production β β
β β (script β MP4 in minutes) β β
β βββββββββββββββββββββ¬βββββββββββββ β
β β β
β βββββββββββββββββββββΌβββββββββββββ β
β β ALERTS & OUTPUT β β
β β Slack / Email / Webhook / CMS β β
β ββββββββββββββββββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Step 1 β Get Your API Keys
Apify
1. Sign up at https://www.apify.com/?fpr=dx06p 2. Go to Settings β Integrations 3. Copy your token: export APIFY_TOKEN=apify_api_xxxxxxxxxxxxxxxx
InVideo
1. Sign up at https://invideo.sjv.io/TBB 2. Go to Settings β API / Developer Settings 3. Copy your key: export INVIDEO_API_KEY=iv_api_xxxxxxxxxxxxxxxx
OpenClaw / Claude API
1. Get your Claude API key from your OpenClaw or Anthropic account 2. Store it: export CLAUDE_API_KEY=sk-ant-xxxxxxxxxxxxxxxx
Step 2 β Install Dependencies
npm install apify-client axios node-cron
Full Pipeline Implementation
Module 1 β Scrape TikTok & Instagram Trends
import ApifyClient from 'apify-client';const apify = new ApifyClient({ token: process.env.APIFY_TOKEN });
// Define hashtags to monitor
const WATCHED_HASHTAGS = [
"viral", "trending", "fyp", "lifehack",
"productivity", "ai", "money", "fitness"
];
async function scrapeTikTokTrends() {
const run = await apify.actor("apify/tiktok-hashtag-scraper").call({
hashtags: WATCHED_HASHTAGS,
resultsPerPage: 50,
shouldDownloadVideos: false
});
const { items } = await run.dataset().getData();
return items.map(item => ({
platform: "tiktok",
hashtag: item.hashtag,
postCount: item.viewCount,
likes: item.diggCount,
shares: item.shareCount,
comments: item.commentCount,
description: item.text,
author: item.authorMeta?.name,
createdAt: item.createTime,
url: item.webVideoUrl
}));
}
async function scrapeInstagramTrends() {
const run = await apify.actor("apify/instagram-hashtag-scraper").call({
hashtags: WATCHED_HASHTAGS,
resultsLimit: 50
});
const { items } = await run.dataset().getData();
return items.map(item => ({
platform: "instagram",
hashtag: item.hashtags?.[0] || "unknown",
likes: item.likesCount,
comments: item.commentsCount,
description: item.caption,
author: item.ownerUsername,
createdAt: item.timestamp,
url: item.url
}));
}
async function scrapeAllPlatforms() {
const [tiktok, instagram] = await Promise.all([
scrapeTikTokTrends(),
scrapeInstagramTrends()
]);
return [...tiktok, ...instagram];
}
Module 2 β Hashtag Explosion Detector
// In-memory baseline (use a database like Redis for production)
const baseline = {};function detectExplosions(currentData) {
const alerts = [];
// Group by hashtag and calculate engagement scores
const grouped = currentData.reduce((acc, post) => {
if (!acc[post.hashtag]) acc[post.hashtag] = { posts: 0, totalLikes: 0, platforms: new Set() };
acc[post.hashtag].posts++;
acc[post.hashtag].totalLikes += post.likes || 0;
acc[post.hashtag].platforms.add(post.platform);
return acc;
}, {});
for (const [hashtag, stats] of Object.entries(grouped)) {
const prev = baseline[hashtag] || { posts: 0, totalLikes: 0 };
const growthRate = prev.posts > 0
? ((stats.posts - prev.posts) / prev.posts) * 100
: 100;
// Alert if posts grew more than 40% since last check
if (growthRate > 40) {
alerts.push({
hashtag,
growthRate: Math.round(growthRate),
currentPosts: stats.posts,
previousPosts: prev.posts,
totalLikes: stats.totalLikes,
platforms: [...stats.platforms],
detectedAt: new Date().toISOString(),
severity: growthRate > 100 ? "EXPLOSIVE" : "RISING"
});
}
// Update baseline
baseline[hashtag] = stats;
}
return alerts.sort((a, b) => b.growthRate - a.growthRate);
}
Module 3 β AI Analysis with Claude (OpenClaw)
json|``import axios from 'axios';;async function analyzeWithClaude(trendData, explosionAlerts) { const prompt =
You are a viral content strategist. Analyze these trending social media data and provide actionable output.TRENDING DATA (last scrape)
${JSON.stringify(trendData.slice(0, 20), null, 2)}EXPLOSION ALERTS
${JSON.stringify(explosionAlerts, null, 2)}Respond ONLY in this exact JSON format, no preamble: { "topTrends": [ { "hashtag": "#example", "whyItsTrending": "brief explanation", "targetAudience": "who this appeals to", "contentAngle": "unique angle to take on this trend" } ], "contentIdeas": [ { "title": "video title idea", "hashtag": "#hashtag", "hook": "first 3 seconds script", "format": "tutorial | reaction | storytime | list | pov", "estimatedViralPotential": "high | medium | low", "reasoning": "why this would perform well" } ], "urgentAlerts": [ { "hashtag": "#hashtag", "message": "alert message", "recommendedAction": "what to do right now", "windowOfOpportunity": "estimated hours before trend peaks" } ], "bestTimeToPost": "recommendation based on trend timing" }
const response = await axios.post( 'https://api.anthropic.com/v1/messages', { model: "claude-opus-4-5", max_tokens: 2000, messages: [{ role: "user", content: prompt }] }, { headers: { 'x-api-key': process.env.CLAUDE_API_KEY, 'anthropic-version': '2023-06-01', 'Content-Type': 'application/json' } } );
const raw = response.data.content[0].text; const clean = raw.replace(/
/g, '').trim();
return JSON.parse(clean);
}
Module 4 β Auto Script Generation
javascript
async function generateVideoScript(contentIdea, trendContext) {
const prompt =
Write a complete short-form video script for this content idea.CONTENT IDEA: ${JSON.stringify(contentIdea)} TREND CONTEXT: ${trendContext}
Respond ONLY in this JSON format: { "title": "video title", "duration": "estimated seconds", "hook": "opening line β first 3 seconds", "fullScript": "complete word-for-word script", "captions": ["caption 1", "caption 2", "..."], "hashtags": ["#tag1", "#tag2", "#tag3"], "cta": "call to action at the end", "thumbnailIdea": "description of ideal thumbnail" }
Rules:
; const response = await axios.post(
'https://api.anthropic.com/v1/messages',
{
model: "claude-opus-4-5",
max_tokens: 1000,
messages: [{ role: "user", content: prompt }]
},
{
headers: {
'x-api-key': process.env.CLAUDE_API_KEY,
'anthropic-version': '2023-06-01',
'Content-Type': 'application/json'
}
}
);
const raw = response.data.content[0].text;
return JSON.parse(raw.replace(/
`json|`/g, '').trim());
}
Module 5 β Auto Video Production with InVideo
javascript
const invideo = axios.create({
baseURL: 'https://api.invideo.io/v1',
headers: { Authorization: Bearer ${process.env.INVIDEO_API_KEY} }
});async function produceVideo(script) {
// Start generation
const { data } = await invideo.post('/videos/generate', {
script: script.fullScript,
format: "9:16",
duration: "short",
style: "dynamic",
voiceover: { enabled: true, voice: "en-US-female-1", speed: 1.1 },
captions: { enabled: true, style: "bold-bottom", highlight: true },
music: { enabled: true, mood: "upbeat", volume: 0.25 },
cta: { enabled: true, text: script.cta, position: "bottom" }
});
const videoId = data.videoId;
// Poll until ready
let exportUrl = null;
while (!exportUrl) {
await new Promise(r => setTimeout(r, 6000));
const status = await invideo.get(
/videos/${videoId}/status);
if (status.data.state === "completed") exportUrl = status.data.exportUrl;
if (status.data.state === "failed") throw new Error("Video generation failed");
console.log( Video progress: ${status.data.progress}%);
} return { videoId, exportUrl, script };
}
Module 6 β Alerts & Notifications
javascript
async function sendAlert(alert, analysis) {
const payload = {
text: π¨ *TREND ALERT: ${alert.hashtag}* β ${alert.severity},
blocks: [
{
type: "section",
text: {
type: "mrkdwn",
text: *π ${alert.hashtag}* grew *${alert.growthRate}%* in the last check\n +
Platforms: ${alert.platforms.join(', ')}\n +
Window: ${analysis.urgentAlerts?.[0]?.windowOfOpportunity || 'Act now'}
}
},
{
type: "section",
text: {
type: "mrkdwn",
text: *π‘ Recommended action:*\n${analysis.urgentAlerts?.[0]?.recommendedAction || 'Create content immediately'}
}
}
]
}; // Send to Slack webhook
if (process.env.SLACK_WEBHOOK_URL) {
await axios.post(process.env.SLACK_WEBHOOK_URL, payload);
}
// Or send to any custom webhook
if (process.env.ALERT_WEBHOOK_URL) {
await axios.post(process.env.ALERT_WEBHOOK_URL, {
type: "trend_explosion",
alert,
analysis,
timestamp: new Date().toISOString()
});
}
}
Main Orchestrator β Full Pipeline
javascript
import cron from 'node-cron';async function runTrendRadar() {
console.log(
\nπ Trend Radar scan started at ${new Date().toISOString()}); try {
// 1 β Scrape all platforms
console.log(" [1/5] Scraping TikTok & Instagram...");
const trendData = await scrapeAllPlatforms();
console.log(
β
${trendData.length} posts collected); // 2 β Detect explosions
console.log(" [2/5] Detecting explosions...");
const alerts = detectExplosions(trendData);
console.log(
β
${alerts.length} alerts detected); // 3 β AI analysis
console.log(" [3/5] Analyzing with Claude...");
const analysis = await analyzeWithClaude(trendData, alerts);
console.log(
β
${analysis.contentIdeas?.length} content ideas generated); // 4 β Auto-generate scripts for top 2 ideas
console.log(" [4/5] Generating video scripts...");
const topIdeas = analysis.contentIdeas?.slice(0, 2) || [];
const scripts = await Promise.all(
topIdeas.map(idea => generateVideoScript(idea, JSON.stringify(analysis.topTrends)))
);
console.log(
β
${scripts.length} scripts written); // 5 β Produce videos
console.log(" [5/5] Producing videos with InVideo...");
const videos = await Promise.all(scripts.map(produceVideo));
console.log(
β
${videos.length} videos ready); // 6 β Send alerts
if (alerts.length > 0) {
await sendAlert(alerts[0], analysis);
console.log(" β
Alerts sent");
}
// Final report
return {
scannedAt: new Date().toISOString(),
postsAnalyzed: trendData.length,
explosionAlerts: alerts,
contentIdeas: analysis.contentIdeas,
videos: videos.map(v => ({ title: v.script.title, url: v.exportUrl })),
bestTimeToPost: analysis.bestTimeToPost
};
} catch (err) {
console.error("Radar error:", err.message);
throw err;
}
}
// Schedule: run every 4 hours automatically
cron.schedule('0 */4 * * *', () => {
runTrendRadar().then(report => {
console.log("\nπ RADAR REPORT:", JSON.stringify(report, null, 2));
});
});
// Also run immediately on startup
runTrendRadar();
Environment Variables
bash
.env
APIFY_TOKEN=apify_api_xxxxxxxxxxxxxxxx
INVIDEO_API_KEY=iv_api_xxxxxxxxxxxxxxxx
CLAUDE_API_KEY=sk-ant-xxxxxxxxxxxxxxxxOptional alerts
SLACK_WEBHOOK_URL=https://hooks.slack.com/services/xxx/xxx/xxx
ALERT_WEBHOOK_URL=https://your-app.com/webhooks/trends
Normalized Radar Report Schema
json
{
"scannedAt": "2025-02-25T10:00:00Z",
"postsAnalyzed": 400,
"explosionAlerts": [
{
"hashtag": "#aitools",
"severity": "EXPLOSIVE",
"growthRate": 187,
"platforms": ["tiktok", "instagram"],
"windowOfOpportunity": "4β8 hours"
}
],
"contentIdeas": [
{
"title": "5 AI tools that replaced my entire team",
"hashtag": "#aitools",
"hook": "I fired my team. Here's what I replaced them with.",
"format": "list",
"estimatedViralPotential": "high"
}
],
"videos": [
{
"title": "5 AI tools that replaced my entire team",
"url": "https://cdn.invideo.io/exports/iv_xxx.mp4"
}
],
"bestTimeToPost": "Post within the next 3 hours while the trend is rising"
}
`
Best Practices
Run the radar every 2β4 hours β trends peak fast and fade within 24β48h
Monitor 8β15 hashtags max per run to stay within Apify free tier
Always produce content within the rising phase β never wait for the peak
Use node-cron` for local scheduling or Apify Schedules for cloud automation
Requirements
π Tips & Best Practices
node-cron for local scheduling or Apify Schedules for cloud automation