threads-bot
v1.0.0
Published
Threads (threads.com) automation library — cookie/credential auth, language-independent direct private-API client. Post (text/image/video/carousel), reply, quote, like, follow, repost, mute/block/restrict, search, feed, notifications, media download, prof
Maintainers
Readme
threads-bot
Full-featured automation library for Threads (threads.com). Cookie- or credential-based auth and a direct private-API client — fast and lightweight, talking straight to the API (no UI scraping).
No browser is required at runtime — everything runs over plain HTTP.
puppeteer-coreis an optional dependency used only for credential login and self-healing.
🌍 Language / Dil: English · Türkçe
English
Features
- Auth — cookies (browser-export array / object / string / file) or username+password login (real-browser, cached, auto-relogin on session loss)
- Posts — text, image, video, carousel (multi-image), reply (any nesting depth), quote (embeds the original), delete
- Interactions — like/unlike, follow/unfollow, repost/unrepost, mute/unmute, block/unblock, restrict/unrestrict
- Reading — feed (for-you/following + pagination), profile & posts, single thread + replies, post counts, notifications, user/keyword search
- Media — download a post's images/videos; upload from local files
- Profile — edit bio/name/link/privacy, change/remove profile photo
- Live events — poll notifications and emit typed events (
follow,like,reply,mention,repost,quote) to build reactive bots - Resilient — retry + exponential backoff, never crashes on
429(throws a catchableRateLimitError)
Install
npm install threads-bot
# optional — only for credential login / self-healing:
npm install puppeteer-coreRequires Node.js ≥ 18 (uses the global fetch).
Quick start
const { ThreadsClient } = require("threads-bot");
const t = new ThreadsClient({ cookies: "./cookies.json" });
await t.init();
await t.createPost("Hello from threads-bot! 🤖");
const feed = await t.getFeed({ limit: 10 });
await t.like(feed.items[0].id);
await t.follow("zuck");Authentication
Option A — cookies. Export your threads.com cookies (e.g. with a "Cookie-Editor" extension) and pass them in any form:
new ThreadsClient({ cookies: "./cookies.json" }); // path to a .json
new ThreadsClient({ cookies: [{ name: "sessionid", value: "…" }, …] }); // browser-export array
new ThreadsClient({ cookies: { sessionid: "…", ds_user_id: "…", csrftoken: "…" } });
new ThreadsClient({ cookies: "sessionid=…; ds_user_id=…; csrftoken=…" }); // cookie stringRequired cookies: sessionid, ds_user_id, csrftoken. Recommended: ig_did, mid, rur.
Option B — credentials. Logs in via a real Chrome window (needs
puppeteer-core + Chrome), caches the cookies, and auto-relogins if the
session expires mid-run:
const t = new ThreadsClient({
credentials: { username: "you", password: "secret" },
cookieFile: "./cookies.json", // cached here and reused next run
loginHeadless: false, // visible window lets you solve 2FA/checkpoints
});
await t.init();💡 Cookies exported from another device tend to get invalidated after writes. For a stable session, log in with credentials from the machine that runs the bot — those cookies are IP-bound.
API reference
Reading
| Method | Returns |
|---|---|
| me() / viewer() | The logged-in user |
| getFeed({ variant, cursor, limit }) | { items, pageInfo } — variant: "for_you" \| "following" |
| iterateFeed({ max, variant }) | async generator over posts |
| getUser(idOrUsername) | Profile |
| getUserPosts(idOrUsername, { cursor, limit }) | { items, pageInfo } |
| getThread(postId) | { post, replies, pageInfo } |
| getReplies(postId, { cursor, limit, sort }) | Replies (works on a reply too → nested comments) |
| getPostCounts(ids) | { counts: [{ likeCount, replyCount, repostCount, quoteCount }] } |
| getNotifications({ cursor, limit }) | Activity feed |
| searchUsers(q) · searchTags(q) · search(q) | Search |
| resolveUserId(username) | @username → numeric id |
Writing & interactions
| Method | Description |
|---|---|
| createPost(text, { media, replyTo, replyControl }) | media = an image/video path, or an array of images for a carousel |
| reply(postId, text) · quote(postId, text) | Reply (nestable) · quote (embeds original) |
| like(id) / unlike(id) | Like / unlike |
| follow(u) / unfollow(u) | Follow / unfollow |
| repost(id) / unrepost(id) | Repost / remove repost |
| mute(u) / unmute(u) | Mute / unmute |
| block(u) / unblock(u) | Block / unblock |
| restrict(u) / unrestrict(u) | Restrict / unrestrict |
| deletePost(id) | Delete your own post |
Media & profile
| Method | Description |
|---|---|
| downloadMedia(postOrId, { dir }) | Download a post's images/videos to disk |
| getMediaUrls(postOrId) | List a post's media URLs |
| updateProfile({ bio, name, link, isPrivate }) | Edit profile (unset fields keep their current value) |
| setProfilePhoto(file) / removeProfilePhoto() | Change / remove profile photo |
Live events (build a reactive bot)
Threads has no webhooks, so the client polls notifications on an interval you choose and emits typed events:
client.on("follow", (e) => client.follow(e.fromUser.id)); // auto follow-back
client.on("reply", (e) => client.reply(e.postId, "thanks! 🙏")); // auto-reply
client.on("mention", (e) => client.reply(e.postId, "👀"));
client.on("like", (e) => console.log("liked by", e.fromUser.username));
client.on("rateLimited", () => console.log("backing off…"));
client.startListening({ intervalMs: 60000 });
// client.stopListening();Events: notification (every item) + follow · like · reply · mention ·
repost · quote · followRequest. Payload: { id, type, fromUser:{ id, username }, postId, text, raw }.
The loop is resilient — a failed poll (incl. 429) keeps the loop alive.
Rate limits
Every request retries on 429/5xx with exponential backoff (honoring
Retry-After); if still limited it throws a catchable RateLimitError — it
never crashes the process. Pace bursty loops:
const { RateLimitError } = require("threads-bot");
try { await client.follow(id); }
catch (e) { if (e instanceof RateLimitError) await sleep(60_000); else throw e; }Events emitted by the client
ready · loginRequired · error · login · postCreated · liked ·
followed · reposted · blocked · profileUpdated · closed — plus the
listener events above.
How it works
The library reverse-engineers threads.com's web app: GraphQL persisted queries
(/graphql/query, /api/graphql) for reads and most mutations, and IG-style
REST (/api/v1/media/configure_*, rupload_*) for posting/media. Session
tokens (lsd, fb_dtsg) are bootstrapped from the home page HTML over plain
HTTP. Because it talks to the API directly, it needs no browser at runtime.
Disclaimer
Unofficial. Not affiliated with Meta or Threads. Uses private endpoints that may change without notice and may be against the Threads Terms of Service. For automating your own account — use responsibly and at your own risk.
Türkçe
Threads (threads.com) için tam kapsamlı otomasyon kütüphanesi. Cookie veya kullanıcı adı+şifre ile giriş, ve doğrudan private-API istemcisi — hızlı ve hafif, doğrudan API ile konuşur (arayüz kazıma yok).
Çalışma anında tarayıcı gerekmez — her şey düz HTTP üzerinden döner.
puppeteer-coreyalnızca credential login ve self-healing için opsiyonel bir bağımlılıktır.
Özellikler
- Giriş — cookie (tarayıcı-export array / obje / string / dosya) veya kullanıcı adı+şifre (gerçek tarayıcı, cache'li, session düşünce otomatik yeniden giriş)
- Gönderiler — metin, görsel, video, carousel (çoklu görsel), yanıt (sınırsız iç içe), alıntı (orijinali gömer), silme
- Etkileşim — beğen/geri al, takip et/bırak, repost/geri al, sustur/aç, engelle/kaldır, kısıtla/kaldır
- Okuma — feed (senin için/takip + sayfalama), profil & gönderiler, gönderi + yanıtlar, sayaçlar, bildirimler, kullanıcı/kelime arama
- Medya — gönderinin görsel/videolarını indir; yerel dosyadan yükle
- Profil — bio/ad/link/gizlilik düzenle, profil fotoğrafı değiştir/kaldır
- Canlı event — bildirimleri yoklayıp tipli event yayar (
follow,like,reply,mention,repost,quote) → tepkisel botlar - Dayanıklı — retry + üstel backoff,
429'da asla çökmez (yakalanabilirRateLimitErrorfırlatır)
Kurulum
npm install threads-bot
# opsiyonel — sadece credential login / self-healing için:
npm install puppeteer-coreNode.js ≥ 18 gerekir (global fetch kullanır).
Hızlı başlangıç
const { ThreadsClient } = require("threads-bot");
const t = new ThreadsClient({ cookies: "./cookies.json" });
await t.init();
await t.createPost("threads-bot'tan selam! 🤖");
const feed = await t.getFeed({ limit: 10 });
await t.like(feed.items[0].id);
await t.follow("zuck");Kimlik doğrulama
Seçenek A — cookie. threads.com cookie'lerini ("Cookie-Editor" eklentisi gibi) dışa aktar ve istediğin biçimde ver:
new ThreadsClient({ cookies: "./cookies.json" }); // .json yolu
new ThreadsClient({ cookies: [{ name: "sessionid", value: "…" }, …] }); // tarayıcı-export dizi
new ThreadsClient({ cookies: { sessionid: "…", ds_user_id: "…", csrftoken: "…" } });
new ThreadsClient({ cookies: "sessionid=…; ds_user_id=…; csrftoken=…" }); // cookie stringZorunlu cookie'ler: sessionid, ds_user_id, csrftoken. Önerilen: ig_did, mid, rur.
Seçenek B — kullanıcı adı/şifre. Gerçek bir Chrome penceresinde giriş yapar
(puppeteer-core + Chrome gerekir), cookie'leri cache'ler ve session düşerse
otomatik yeniden giriş yapar:
const t = new ThreadsClient({
credentials: { username: "sen", password: "gizli" },
cookieFile: "./cookies.json", // burada cache'lenir, sonraki çalışmada kullanılır
loginHeadless: false, // görünür pencere 2FA/checkpoint çözmeni sağlar
});
await t.init();💡 Başka cihazdan export edilen cookie'ler write işlemlerinden sonra geçersiz kılınabilir. Kararlı session için botu çalıştıracağın makineden credential ile giriş yap — o cookie'ler o IP'ye bağlıdır.
API başvurusu
Okuma
| Metot | Döner |
|---|---|
| me() / viewer() | Giriş yapan kullanıcı |
| getFeed({ variant, cursor, limit }) | { items, pageInfo } — variant: "for_you" \| "following" |
| iterateFeed({ max, variant }) | gönderiler üzerinde async generator |
| getUser(idVeyaKullanıcıAdı) | Profil |
| getUserPosts(idVeyaKullanıcıAdı, { cursor, limit }) | { items, pageInfo } |
| getThread(postId) | { post, replies, pageInfo } |
| getReplies(postId, { cursor, limit, sort }) | Yanıtlar (bir yanıt id'siyle → iç içe yorumlar) |
| getPostCounts(ids) | { counts: [{ likeCount, replyCount, repostCount, quoteCount }] } |
| getNotifications({ cursor, limit }) | Bildirim akışı |
| searchUsers(q) · searchTags(q) · search(q) | Arama |
| resolveUserId(kullanıcıAdı) | @kullanıcı → sayısal id |
Yazma & etkileşim
| Metot | Açıklama |
|---|---|
| createPost(text, { media, replyTo, replyControl }) | media = görsel/video yolu, ya da carousel için görsel dizisi |
| reply(postId, text) · quote(postId, text) | Yanıt (iç içe) · alıntı (orijinali gömer) |
| like(id) / unlike(id) | Beğen / geri al |
| follow(u) / unfollow(u) | Takip et / bırak |
| repost(id) / unrepost(id) | Repost / geri al |
| mute(u) / unmute(u) | Sustur / aç |
| block(u) / unblock(u) | Engelle / kaldır |
| restrict(u) / unrestrict(u) | Kısıtla / kaldır |
| deletePost(id) | Kendi gönderini sil |
Medya & profil
| Metot | Açıklama |
|---|---|
| downloadMedia(postVeyaId, { dir }) | Gönderinin görsel/videolarını diske indir |
| getMediaUrls(postVeyaId) | Gönderinin medya URL'leri |
| updateProfile({ bio, name, link, isPrivate }) | Profili düzenle (verilmeyen alan mevcut değerini korur) |
| setProfilePhoto(dosya) / removeProfilePhoto() | Profil fotoğrafını değiştir / kaldır |
Canlı event (tepkisel bot)
Threads'in webhook'u yok; istemci bildirimleri senin belirlediğin aralıkta yoklar ve tipli event yayar:
client.on("follow", (e) => client.follow(e.fromUser.id)); // otomatik geri takip
client.on("reply", (e) => client.reply(e.postId, "teşekkürler 🙏")); // yoruma yanıt
client.on("mention", (e) => client.reply(e.postId, "👀"));
client.on("like", (e) => console.log(e.fromUser.username, "beğendi"));
client.on("rateLimited", () => console.log("yavaşlıyor…"));
client.startListening({ intervalMs: 60000 });
// client.stopListening();Event'ler: notification (her öğe) + follow · like · reply · mention ·
repost · quote · followRequest. Payload: { id, type, fromUser:{ id, username }, postId, text, raw }.
Döngü dayanıklıdır — başarısız bir poll (429 dahil) döngüyü durdurmaz.
Rate limit
Her istek 429/5xx'te üstel backoff ile retry yapar (Retry-After'a
saygılı); hâlâ limitliyse yakalanabilir RateLimitError fırlatır — process
asla çökmez. Yoğun döngüleri yavaşlat:
const { RateLimitError } = require("threads-bot");
try { await client.follow(id); }
catch (e) { if (e instanceof RateLimitError) await sleep(60_000); else throw e; }Nasıl çalışır
Kütüphane threads.com web uygulamasını reverse-engineer eder: okuma ve çoğu
mutation için GraphQL persisted query'ler (/graphql/query, /api/graphql),
gönderi/medya için IG-tarzı REST (/api/v1/media/configure_*, rupload_*).
Session token'ları (lsd, fb_dtsg) ana sayfa HTML'inden düz HTTP ile alınır.
API ile doğrudan konuştuğu için çalışma anında tarayıcı gerektirmez.
Sorumluluk reddi
Resmi değildir. Meta veya Threads ile bağlantılı değildir. Haber verilmeden değişebilen ve Threads Kullanım Şartları'na aykırı olabilen özel endpoint'ler kullanır. Kendi hesabını otomatikleştirmek içindir — sorumlu kullan, risk sana aittir.
License / Lisans
MIT © alpersamur3
