Social Comment Classifier — buying intent & questions · $0.5/1k
Pricing
from $0.43 / 1,000 comment classifications
Social Comment Classifier — buying intent & questions · $0.5/1k
Classify Instagram, TikTok, Facebook, YouTube comments: buying intent, sentiment — Instagram comments sentiment and TikTok comments analyzer. Use for comments; for reviews use leoworks/korean-review-classifier. datasetId (text auto-detected) or texts. ~100 comments/4 s, pay per comment.
Pricing
from $0.43 / 1,000 comment classifications
Rating
5.0
(1)
Developer
Leoworks
Maintained by CommunityActor stats
0
Bookmarked
3
Total users
2
Monthly active users
10 days ago
Last modified
Categories
Share
Social Comment Classifier — purchase intent, questions & sentiment
Part of LeoWorks review analysis tools (same labels, any language): Korean · Japanese · Spanish · Amazon · AliExpress · Google Maps · social comments.
For brands, social media managers, agencies and AI agents that already scrape comments — from an Instagram, TikTok, Facebook or YouTube comment scraper, any other Apify dataset, or pasted as text — and need an Instagram comments sentiment and TikTok comments analyzer — every comment labelled by what it is, for $0.50 per 1,000 comments, with no prompt writing or LLM key. It is an Instagram comment sentiment analysis and TikTok comment sentiment analysis tool, with YouTube comments analysis too.
- Comment type —
purchase_intent·question·complaint·request·praise·spam·other(one main type, with a probability for every type) - Sentiment — positive / neutral / negative
- Needs reply — whether the brand or creator should answer (questions, problems, "how do I buy?")
- Reply queue — comments that need an answer (buyers first, then complaints, questions, requests), most-liked first, as a CSV
- Summary by post — type mix (also weighted by likes), sentiment, reply-needed count, languages, daily trend and last 7 days vs before, the most-liked buying questions and complaints — as JSON and CSV
- Your own labels — up to 10 yes/no criteria in plain language (e.g. "mentions shipping or delivery", "asks about a discount code")
- No wasted spend — the post owner's own replies, duplicates, and (optionally) replies, emoji-only or low-like comments are skipped and not charged
Use it to: find buyers in your comments ("price?", "link?", "when is the restock?") · answer unanswered questions · catch complaints before they spread · hide spam and fake-shop promotion · collect product requests · Instagram, TikTok and YouTube comment sentiment analysis at scale · compare comment mix across posts or competitors.
How to use
- Run a comment scraper for your posts or a competitor's — for example Instagram Comments Scraper or TikTok Comments Scraper (see Works with for 15 more).
- Open this Actor and pick that run's dataset in Comments dataset (or paste comments to try it).
- Optional: add Custom labels; list your own brand accounts in Exclude accounts; set Only comments newer than: 7 days. Skipped comments are not charged.
- Click Start. 9 comments take about 3 seconds.
- In Output, open Classified comments, Needs a reply or Labels with probabilities, or download
REPLY_QUEUE.csvandREPORT_POSTS.csv. Export the table as CSV, Excel or JSON.
Run it automatically after every scrape
In your comment scraper (or its saved task), open Integrations → Add integration → Apify Actor, choose this Actor and set its input to:
{ "datasetId": "{{resource.defaultDatasetId}}", "commentsNewerThan": "1 day" }
Schedule the scraper daily and you get a fresh reply queue every morning. Add a Slack or email integration on this Actor to be told when it finishes.
Output sample
Real rows from run tphg77KXmZ9fMS6Pg (2026-10-11, build 0.2.2; same labels as the first run PgvMClRhIRV9gKmp7 on 2026-10-09): public comments from the four comment scrapers below, with one custom label ("mentions shipping or delivery").
| comment | source | type (probability) | sentiment | needs reply | custom: shipping |
|---|---|---|---|---|---|
| When will you restock Generation G Fuzz? | purchase_intent (1.00) | neutral | yes | no | |
| Link | Facebook (live shopping) | purchase_intent (0.50) | neutral | no | no |
| How much do they hold? | question (1.00) | neutral | yes | no | |
| Temu, you guys are up over here making tiktoks. When im still am waiting for my package… | TikTok | complaint (1.00) | negative | yes | yes |
| I would like a refund for the 2 weeks the towers were down in my area. | complaint (0.94) | negative | yes | no | |
| can y'all make the resurfacing retinol serum in a bigger bottle ? | TikTok | request (1.00) | neutral | yes | no |
| obsessed with every single one of these! | praise (1.00) | positive | no | no | |
| For me personally… I do buy quality fakes/knockoffs at (shop name) | YouTube | spam (0.75) | neutral | no | no |
Each row also keeps the comment ID and post fields you choose (id, cid, postUrl, videoWebUrl, …), and in full mode typeScores with the probability of every type.
Input example
The form default — two pasted comments, no dataset needed (about $0.001, 2 seconds):
{"texts": ["Where can I buy this in Canada? Need it!!","Ordered 3 weeks ago and still nothing. Is anyone answering messages?"]}
To classify a comment scraper's output, pass its dataset instead — the text, post, date, likes, reply flag and IDs are detected automatically:
{"datasetId": "YOUR_COMMENTS_DATASET_ID","commentsNewerThan": "7 days","excludeAuthors": ["yourbrand", "yourbrand_support"],"customLabels": ["mentions shipping or delivery"]}
Pricing
Pay only for classified comments — no subscription.
| Event | Price | When |
|---|---|---|
comment-judged | $0.0005 | One comment classified (type such as purchase intent, question or complaint; sentiment; needs-reply flag and any custom labels). |
That is $0.50 per 1,000 comments. First run with the form defaults: about $0.001 (2 comments, 2 seconds).
Cost examples
| Comments | Cost |
|---|---|
| 100 | $0.05 |
| 1,000 | $0.50 |
| 10,000 | $5.00 |
| 100,000 | $50.00 |
With the free $5 monthly Apify credit you can classify about 10,000 comments.
Items without comment text are skipped and not charged. Comments that fail after retries are reported with an error field and not charged. If you set a maximum cost per run, the Actor stops cleanly when it is reached.
Works with
Field names are matched ignoring case, _ and - (also inside user.username-style objects), like counts such as "3.4K" are read as numbers, relative dates such as "3 days ago" are counted back from the run time, and nested replies are flattened. The first four were checked against real output (2026-10-09); the others against each scraper's published output schema (2026-10-11).
| Platform | Scraper on Apify Store | Text | Post | Likes | Date | Reply / owner flag |
|---|---|---|---|---|---|---|
| Instagram Comments Scraper (apify) | text | postUrl | likesCount | timestamp | nested replies[] | |
| TikTok | TikTok Comments Scraper (clockworks) | text | videoWebUrl | diggCount | createTimeISO | repliesToId |
| Facebook Comments Scraper (apify) | text | facebookUrl | likesCount (text) | date | threadingDepth, nested comments[] | |
| YouTube | YouTube Comments Scraper (streamers) | comment | videoId | voteCount | publishedTimeText (relative) | type, authorIsChannelOwner |
| TikTok | apidojo, xtdata TikTok comment scrapers | text | awemeId / aweme_id | likeCount / digg_count | createdAt / create_time | parentId / reply_id |
| apidojo, supreme_coder, scrapesmith, datadoping, louisdeconinck | text / message | postId, postUrl, media_id, input_url | likesCount / like_count | timestamp / created_at | type, depth, parentCommentId | |
| Instagram Scraper (apify), posts mode | latestComments[] (flattened) | url | likesCount | timestamp | — | |
| thedoor, chronometrica, dami_studio | text | post_url, postUrl, facebookUrl | reactions_count, reactionsCount, likesCount | comment_time, publishedAt, date | isReply, threadingDepth | |
| YouTube | apidojo, solidcode | text | videoId | likeCount ("3.4K") | publishedTime, publishedAt | isCreatorReply |
| harvestapi LinkedIn post comments | commentary | postId | — | createdAt | type |
Rows without comment text (post rows, video info rows) are skipped and not charged. Anything still not detected can be set under Field mapping & advanced. Also: the Apify API and JavaScript/Python clients · Apify Schedules · Claude, Cursor and Claude Code through the Apify MCP server (below) · for product reviews, our Amazon, Google Maps, Korean and AliExpress review classifiers.
Call it from code
curl -X POST "https://api.apify.com/v2/acts/leoworks~social-comment-classifier/run-sync-get-dataset-items?token=YOUR_APIFY_TOKEN" \-H "Content-Type: application/json" \-d '{"datasetId": "YOUR_DATASET_ID", "commentsNewerThan": "7 days"}'
JavaScript (npm install apify-client):
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: 'YOUR_APIFY_TOKEN' });const run = await client.actor('leoworks/social-comment-classifier').call({ datasetId: 'YOUR_DATASET_ID' });const { items } = await client.dataset(run.defaultDatasetId).listItems();const buyers = items.filter((c) => c.type === 'purchase_intent');
Python (pip install apify-client):
from apify_client import ApifyClientclient = ApifyClient("YOUR_APIFY_TOKEN")run = client.actor("leoworks/social-comment-classifier").call(run_input={"datasetId": "YOUR_DATASET_ID"})items = client.dataset(run["defaultDatasetId"]).list_items().itemsto_answer = [c for c in items if c.get("needsReply")]
Use with Claude, Cursor or Claude Code (MCP)
Ask your AI agent. Add the Apify MCP server with this Actor as a tool, then say, for example:
- "Which of these comments are from people who want to buy? “Where can I buy this in Canada? Need it!!” / “Ordered 3 weeks ago and still nothing. Is anyone answering messages?” / “Love the colour 😍”"
- "Classify dataset YOUR_DATASET_ID from my TikTok comments scraper run and list the unanswered questions and complaints first."
- "Which of these Instagram comments are spam and which need a reply? “Follow me for free gift cards!!” / “Does it come in size L?” / “Not working, I want my money back.”"
The agent calls the tool leoworks--social-comment-classifier and reads the labels with get-dataset-items. Replace YOUR_DATASET_ID with the ID of your own dataset.
Claude Desktop or Cursor (mcp.json):
{"mcpServers": {"apify": {"url": "https://mcp.apify.com?tools=leoworks/social-comment-classifier","headers": { "Authorization": "Bearer YOUR_APIFY_TOKEN" }}}}
Claude Code: claude mcp add --transport http apify "https://mcp.apify.com?tools=leoworks/social-comment-classifier" --header "Authorization: Bearer YOUR_APIFY_TOKEN". Leave out the header to sign in with OAuth in the browser instead. Your Apify token is in Console → Settings → API & Integrations. We verified this setup with the Apify MCP server (v0.17.4) on 2026-10-09: the agent classified a pasted comment in 6 seconds end to end (run XTdACdD0TchL5eQ34).
Output
| Where | What |
|---|---|
| Dataset — view Classified comments | One row per comment with flat, spreadsheet-friendly columns |
| Dataset — view Needs a reply | Type, likes, date, comment, post and link — filter needsReply = true |
| Dataset — view Labels with probabilities | Every label with its probability, including all seven type scores |
REPLY_QUEUE.csv | Comments that need an answer: purchase intent, then complaints, questions and requests; most-liked first |
REPORT_POSTS.csv | One row per post: comments, share of each type, sentiment, reply-needed count, top language, last 7 days vs before |
REPORT (JSON) | The same per post plus like-weighted type shares, daily trend (30 days) and the most-liked example comments per type |
BUYERS.csv | Only with Include commenter usernames: one row per commenter who showed purchase intent |
SUMMARY (JSON) | Detected fields, filters and counts, including skipped owner replies and duplicates |
Nothing extra is charged for the files.
One row
From run tphg77KXmZ9fMS6Pg (build 0.2.2, a dataset mixing four platforms; typeScores left out):
{"cid": "7694457506550088461","post": "https://www.tiktok.com/@temu/video/7694358584565583117","publishedAt": "2026-10-09T00:25:38.000Z","likes": 0,"replies": 1,"isReply": false,"text": "Temu, you guys are up over here making tiktoks. When im still am waiting for my package like, give me my freaking package, please.","type": "complaint","sentiment": "negative","needsReply": true,"emojiOnly": false,"customLabelsMatched": "mentions shipping or delivery","labels": {"type": { "label": "complaint", "probability": 1, "confidence": 1 },"sentiment": { "label": "negative", "probability": 1, "confidence": 1 },"needsReply": { "probability": 0.85, "matched": true },"custom": [{ "label": "mentions shipping or delivery", "probability": 0.98, "matched": true }]}}
author appears only with Include commenter usernames; language when the scraper gives one. In full mode labels.typeScores lists all seven types. Minimal mode returns IDs and label keys only.
How types are chosen: each comment gets one main type. When a comment fits several, the first in this order wins: spam → purchase_intent → complaint → question → request → praise → other. So "Love it! Where can I buy it in the UK?" is purchase_intent, and "It stopped working after a week, any tips?" is complaint. Use typeScores or Needs reply when you want every comment that asks something.
Summary by post (REPORT)
Each run also saves a REPORT record (Output tab → Summary by post) at no extra charge: for every post, the comment type mix (by count and by likes), sentiment shares, how many comments need a reply, languages, a daily trend with last 7 days vs before, and up to 3 most-liked example comments for purchase intent, questions, complaints and requests — plus the same for all comments together. lowSample is true below 30 classified comments. Posts are grouped by summaryGroupField (detected automatically from fields such as postUrl, videoWebUrl, facebookUrl or videoId when empty).
Illustrative shape (numbers made up for the example):
{"groupField": "videoWebUrl","groups": [{"group": "https://www.tiktok.com/@brand/video/1","comments": 120,"classified": 118,"types": [{ "label": "praise", "count": 51, "share": 0.432 }, { "label": "purchase_intent", "count": 22, "share": 0.186 }],"sentiment": { "positive": 0.55, "neutral": 0.36, "negative": 0.09 },"needsReplyRate": 0.31,"examples": { "purchase_intent": [{ "likes": 14, "text": "price?" }, { "likes": 3, "text": "Do you ship to Canada?" }], "question": [{ "likes": 9, "text": "Is it waterproof?" }] }}]}
Accuracy
Measured on 205 hand-labelled public English comments from Instagram, TikTok, Facebook and YouTube (beauty brands, a mobile carrier, a retailer's live shopping and product review videos; 2026-10-09). The questions were adjusted on one part, then checked once on a separate part that was not used for adjusting.
| Set | Comments | Main type | Main type (either label where two fit) | Sentiment |
|---|---|---|---|---|
| Check set — not used for adjusting | 100 | 90% | 95% | 87% |
| Adjusting set | 105 | 88% | 93% | 84% |
On the check set, complaints were found 97% of the time, questions 100%, spam 86% and purchase intent 71% (7 comments). Short comments without context ("No", "Vibes") are the hardest. Probabilities are calibrated — use typeScores and Label threshold to trade coverage for certainty. Automated labels can be wrong; check samples before making big decisions.
Limits
| Item | Limit |
|---|---|
| Comment length | First 4,000 characters are used (post title: 300) |
| Custom labels | Up to 10, each up to 200 characters |
| Dataset size | Any — datasets are read in pages of 1,000 |
| Language | English (measured). Other languages are accepted and usually work, but accuracy has not been measured — treat them as beta |
| Replies | Each row is classified on its own, without its parent comment. Nested replies (Instagram replies, Facebook comments, Instagram Scraper latestComments) are flattened to rows; turn Classify nested replies off to skip them |
| Speed | About 100 comments in 3–4 seconds |
| Dates | Relative dates ("3 days ago") are approximate — counted back from the run time |
| Data | Only the comment text, the post title and your custom labels are sent for classification. Usernames are never sent; they are copied to the output only when you turn on Include commenter usernames |
Run it on a schedule
Daily is the usual rhythm: schedule your comment scraper with an Apify Schedule, connect this Actor to it (see Run it automatically after every scrape) and set Only comments newer than to 1 day to get a fresh reply queue every morning. To start it from other tools, use the Apify n8n or Make integration, or the Apify API.
Related Actors
Scrapers that collect the input (Apify Store, other publishers — this Actor reads their datasets):
| Scraper | Collects |
|---|---|
| Instagram Comments Scraper (apify) | comments of Instagram posts |
| TikTok Comments Scraper (clockworks) | comments of TikTok videos |
| YouTube Comments Scraper (streamers) | comments of YouTube videos |
More from Leoworks:
| Need | Actor |
|---|---|
| Google Maps reviews | Google Maps Review Classifier |
| Amazon reviews | Amazon Review Classifier |
| Korean reviews | Korean Review Classifier |
FAQ
How is this different from Apify's Comments Analyzer Agent or asking ChatGPT?
Those summarise comments with a language model. This labels every comment with one of seven types and a calibrated probability, so you can count and filter them, and the price is fixed at $0.50 per 1,000 — no prompt to maintain. It also works on the output of any comment scraper you already use.
What are the alternatives to Social Comment Classifier?
The platforms' own inboxes (one account at a time, no labels), a social-listening subscription, or an LLM with your own prompts. This Actor labels comments from any Instagram, TikTok, Facebook or YouTube comment scraper for $0.50 per 1,000 comments.
How do I analyze Instagram and TikTok comments?
Run a comment scraper (see Works with), pick its dataset here and start. Every comment gets a type — filter for purchase_intent to see people asking for price, links or restocks, and for spam to hide fake-shop promotion — plus sentiment.
Which AI makes the judgments?
Jev, TypeSafe's decision model (version jev-1.13.0, pinned). Jev answers each label with a calibrated probability instead of generated text, so a 0.9 means the same thing for every item. Answers are stable but not fixed: re-running the same input can change a few borderline answers (under 1% of answers in our repeat tests) — filter on probability when an item must never flip. Only the comment text, the post title and your custom labels are sent to Jev; usernames and other fields are not.
Does it scrape Instagram, TikTok, Facebook or YouTube?
No. It classifies comments you already have — run a comment scraper first (see Works with) or paste texts.
Does it write replies?
No. It only assigns labels with probabilities — fast, cheap and consistent. Use Needs reply to decide which comments to answer.
Are the brand's own replies charged?
No. Comments flagged by the scraper as written by the channel owner or creator, and any account in Exclude accounts, are skipped before classification. Duplicates are skipped too.
Can I get a list of people who want to buy?
Turn on Include commenter usernames: each row gets the public username from your dataset and the run saves BUYERS.csv with one row per commenter who showed purchase intent. Usernames are never sent for classification. Use them in line with the platform's terms and privacy law.
Can I classify only new comments every day?
Yes. Schedule the scraper, connect this Actor through Integrations (see How to use) with Only comments newer than: 1 day. Older comments and duplicates are skipped and not charged.
Why request as well as complaint?
Product requests ("please make a bigger bottle") are feedback for product teams, not problems for support. They are kept apart so each team gets its own list.
Disclaimer
Independent tool — not affiliated with, endorsed by or sponsored by Meta (Instagram, Facebook), TikTok, Google (YouTube), or by the authors of the scrapers listed above. Names are used only to describe compatible data sources. The comments shown are public comments used as examples.
Reviews and support
If this Actor saved you time, a short review on Apify Store helps others find it. Questions or a dataset whose fields are not detected? Open an issue in the Issues tab — we answer within a day.
Changelog
See the Changelog tab.