Automated TikTok & Instagram Trend Radar

# Automated TikTok & Instagram Trend Radar Skill

Safety Notice

This listing is from the official public ClawHub registry. Review SKILL.md and referenced scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "Automated TikTok & Instagram Trend Radar" with this command: npx skills add g4dr/tiktok-trend-radar

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

  • Scrape TikTok hashtags, sounds, and viral posts every few hours via Apify
  • Scrape Instagram Reels and trending hashtags in parallel
  • Detect hashtag explosions — sudden spikes in post volume or engagement
  • Send raw trend data to Claude for instant AI-powered analysis
  • Auto-generate content ideas, angles, and hooks based on detected trends
  • Write complete video scripts tailored to the trending topic
  • Produce the video automatically via InVideo AI
  • Alert via webhook, Slack, or email when a trend is breaking

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)

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(/```json|```/g, '').trim();
  return JSON.parse(clean);
}

Module 4 — Auto Script Generation

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:
- Hook must create curiosity or shock in under 4 seconds
- Script must be 120–180 words for a 30–45 second video
- Conversational, energetic tone
- End with a strong CTA (follow, comment, share)
`;

  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

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

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

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

# .env
APIFY_TOKEN=apify_api_xxxxxxxxxxxxxxxx
INVIDEO_API_KEY=iv_api_xxxxxxxxxxxxxxxx
CLAUDE_API_KEY=sk-ant-xxxxxxxxxxxxxxxx

# Optional 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

{
  "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
  • Store baseline data in Redis or a database for accurate spike detection in production
  • Pipe the video URLs directly into your social media scheduler (Buffer, Later, etc.)

Requirements

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

yuqing-bitable-and-label

Incrementally sync data from XiaoAi API to Feishu Bitable and optionally auto-label records with machine-based type and sentiment annotations.

Registry SourceRecently Updated
General

张律师综合套装

张律师法律AI中台 - 中国首个开源法律AI技能库,涵盖刑事辩护、民商事诉讼、合同审查全流程

Registry SourceRecently Updated
General

刑事辩护

刑事辩护全流程AI助手 - 6大阶段21个模板,从接案到执行全覆盖

Registry SourceRecently Updated