Skip to content
BuzzTake
MenuClose
DocumentationReply to comments

How to read and reply to comments on your posts

Last updated

Read the comments under your recent posts and answer them through the account that posted. Your code or your agent writes each reply; BuzzTake reads the comments and posts the replies in the account's browser.

You need a BuzzTake API key and the id of an active account.

1. Find the posts to check

Every post the account published with the post action is in its action history, with its URL in result.url. Filter the history to succeeded posts:

GET/v1/accounts/{id}/actions

Request
curl "https://api.buzztake.com/v1/accounts/$ACCOUNT_ID/actions?type=post&status=succeeded&limit=20" \
  -H "Authorization: Bearer $BUZZTAKE_API_KEY"
200 OK (trimmed)
{
  "actions": [
    {
      "id": "0199e5f6-...",
      "type": "post",
      "status": "succeeded",
      "result": { "type": "created", "url": "https://www.instagram.com/p/C0deXyZ/", "id": "C0deXyZ" },
      "finished_at": "2026-10-29T09:00:09Z"
    }
  ],
  "next_cursor": "0199e5f6-..."
}

The history is newest first; pass next_cursor as cursor for older posts. For posts made outside BuzzTake, use their URLs, or the url of comment notifications from read_notifications.

2. Read the comments under a post

POST/v1/accounts/{id}/actions

Run read_post with the post's URL in target. replies is how many comments to read: 20 by default, at most 100. A read costs 4 credits, charged only when it succeeds.

Request
curl https://api.buzztake.com/v1/accounts/$ACCOUNT_ID/actions \
  -H "Authorization: Bearer $BUZZTAKE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "type": "read_post", "target": "https://www.instagram.com/p/C0deXyZ/", "replies": 50, "wait": 60 }'
200 OK (trimmed)
{
  "type": "read_post",
  "status": "succeeded",
  "result": {
    "type": "post",
    "item": { "url": "https://www.instagram.com/p/C0deXyZ/", "text": "Dark mode is live.", "replies": "12" },
    "replies": [
      {
        "url": "https://www.instagram.com/p/C0deXyZ/c/18034.../",
        "id": "18034...",
        "author_handle": "jamie.codes",
        "author_name": "Jamie",
        "text": "Where do I turn it on?",
        "published_at": "2026-10-29T10:14:00Z",
        "likes": "3",
        "media_urls": []
      }
    ]
  },
  "credits": 4
}

item is the post and replies are its comments, each with url, id, author_handle, author_name, text, published_at and the counts as the page shows them. A field the page does not show is null.

3. Choose what each reply answers

reply takes a target. Whether that can be one comment depends on the platform:

PlatformReply target
X, Threads, Bluesky, MastodonThe comment's url. Comments are posts, so you can reply to a reply.
Instagram, Facebook, Reddit, YouTubeThe comment's url. The reply answers that comment.
LinkedInThe post's URL. A reply adds a comment on the post; it cannot answer one comment.
TikTok, PinterestThe post's URL. Their comments come back with no url or id, and a reply adds a comment on the post.
TelegramNo reply action. read_post returns no replies.

4. Reply to each comment

A reply needs target, and text, media or both; comments on LinkedIn, Reddit and Pinterest take text only. It costs 8 credits, charged when it starts. Use an Idempotency-Key made from the comment's id: if your script runs twice, the second run returns the first reply and posts nothing new.

curl

curl
curl https://api.buzztake.com/v1/accounts/$ACCOUNT_ID/actions \
  -H "Authorization: Bearer $BUZZTAKE_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: reply-18034..." \
  -d '{
    "type": "reply",
    "target": "https://www.instagram.com/p/C0deXyZ/c/18034.../",
    "text": "Thanks, @jamie.codes. It is under Settings, Appearance.",
    "wait": 60
  }'

JavaScript

JavaScript
const api = "https://api.buzztake.com/v1";
const accountId = process.env.ACCOUNT_ID;
const ownHandle = "acme_demo";
const headers = {
  Authorization: `Bearer ${process.env.BUZZTAKE_API_KEY}`,
  "Content-Type": "application/json",
};

// Runs one action, waits for it, and returns its result. Throws unless it succeeded.
async function run(body, idempotencyKey) {
  const res = await fetch(`${api}/accounts/${accountId}/actions`, {
    method: "POST",
    headers: idempotencyKey ? { ...headers, "Idempotency-Key": idempotencyKey } : headers,
    body: JSON.stringify({ ...body, wait: 90 }),
  });
  if (!res.ok) throw new Error(`${res.status}: ${await res.text()}`);
  const action = await res.json();
  if (action.status !== "succeeded") {
    throw new Error(`${body.type} ${action.status}: ${action.error?.message ?? ""}`);
  }
  return action.result;
}

const postUrl = "https://www.instagram.com/p/C0deXyZ/";
const { replies } = await run({ type: "read_post", target: postUrl, replies: 50 });

for (const comment of replies) {
  if (!comment.url || comment.author_handle === ownHandle) continue;
  const text = `Thanks, @${comment.author_handle}. It is under Settings, Appearance.`;
  const created = await run(
    { type: "reply", target: comment.url, text },
    `reply-${comment.id ?? comment.url}`,
  );
  console.log(comment.url, "->", created.url);
}

Python

Python
import os
import requests

api = "https://api.buzztake.com/v1"
account_id = os.environ["ACCOUNT_ID"]
own_handle = "acme_demo"
headers = {"Authorization": f"Bearer {os.environ['BUZZTAKE_API_KEY']}"}


def run(body, idempotency_key=None):
    """Runs one action, waits for it, and returns its result. Raises unless it succeeded."""
    extra = {"Idempotency-Key": idempotency_key} if idempotency_key else {}
    resp = requests.post(
        f"{api}/accounts/{account_id}/actions",
        headers={**headers, **extra},
        json={**body, "wait": 90},
        timeout=100,
    )
    if not resp.ok:
        raise SystemExit(f"{resp.status_code}: {resp.text}")
    action = resp.json()
    if action["status"] != "succeeded":
        raise SystemExit(f"{body['type']} {action['status']}: {action.get('error')}")
    return action["result"]


post_url = "https://www.instagram.com/p/C0deXyZ/"
result = run({"type": "read_post", "target": post_url, "replies": 50})

for comment in result["replies"]:
    if not comment.get("url") or comment.get("author_handle") == own_handle:
        continue
    text = f"Thanks, @{comment['author_handle']}. It is under Settings, Appearance."
    created = run(
        {"type": "reply", "target": comment["url"], "text": text},
        f"reply-{comment.get('id') or comment['url']}",
    )
    print(comment["url"], "->", created["url"])

The scripts skip the account's own comments and comments with no URL. Replace the fixed text with your own, or with a reply your model writes from comment.text.

Tip: With an MCP client, ask your agent to read a post with read_post and draft replies for you to confirm. Each reply it sends is a reply tool call at the same price.

Common errors

422 invalid_input
"reply needs text, media, or both"
422 invalid_input
"replies must be a whole number from 0 to 100"
422 unsupported
"Telegram accounts cannot reply. They can: ..." Telegram has no replies.
Action error not_found
The post or comment was deleted, or the account cannot see it.
Action error rate_limited
The platform asked the account to slow down. Space out the replies and try later.

See also

To run this on your own accounts, create a BuzzTake account, then add an account and an API key.