![Deno 2.2 Improves Dependency Management and Expands Node.js Compatibility](https://cdn.sanity.io/images/cgdhsj6q/production/97774ea8c88cc8f4bed2766c31994ebc38116948-1664x1366.png?w=400&fit=max&auto=format)
Security News
Deno 2.2 Improves Dependency Management and Expands Node.js Compatibility
Deno 2.2 enhances Node.js compatibility, improves dependency management, adds OpenTelemetry support, and expands linting and task automation for developers.
threads-api
Advanced tools
Unofficial, Reverse-Engineered Node.js/TypeScript client for Meta's [Threads](https://threads.net).
Unofficial, Reverse-Engineered Node.js/TypeScript client for Meta's Threads.
threads-api
in Action✨ The App Registry is officially live! We invite you to explore it on our website at threads.junho.io.
Modify threads-web-ui/data/apps.ts to add your projects!
import { ThreadsAPI } from 'threads-api';
// or in Deno 🦖:
// import ThreadsAPI from "npm:threads-api";
const main = async () => {
const threadsAPI = new ThreadsAPI();
const username = '_junhoyeo';
// 👤 Details for a specific user
const userID = await threadsAPI.getUserIDfromUsername(username);
if (!userID) {
return;
}
const user = await threadsAPI.getUserProfile(userID);
console.log(JSON.stringify(user));
const posts = await threadsAPI.getUserProfileThreads(userID);
console.log(JSON.stringify(posts));
const replies = await threadsAPI.getUserProfileReplies(userID);
console.log(JSON.stringify(replies));
// 📖 Details for a specific thread
const postID = threadsAPI.getPostIDfromURL(
'https://www.threads.net/t/CuX_UYABrr7/?igshid=MzRlODBiNWFlZA==',
);
// or use `threadsAPI.getPostIDfromThreadID('CuX_UYABrr7')`
if (!postID) {
return;
}
const post = await threadsAPI.getThreads(postID);
console.log(JSON.stringify(post.containing_thread));
console.log(JSON.stringify(post.reply_threads));
const likers = await threadsAPI.getThreadLikers(postID);
console.log(JSON.stringify(likers));
};
main();
getUserProfile
but with authconst userID = '5438123050';
const { user } = await threadsAPI.getUserProfileLoggedIn();
console.log(JSON.stringify(user));
const { items: threads, next_max_id: cursor } = await threadsAPI.getTimeline();
console.log(JSON.stringify(threads));
const { threads, next_max_id: cursor } = await threadsAPI.getUserProfileThreadsLoggedIn(userID);
console.log(JSON.stringify(threads));
const { threads, next_max_id: cursor } = await threadsAPI.getUserProfileRepliesLoggedIn(userID);
console.log(JSON.stringify(threads));
const { users, next_max_id: cursor } = await threadsAPI.getUserFollowers(userID);
console.log(JSON.stringify(users));
const { users, next_max_id: cursor } = await threadsAPI.getUserFollowings(userID);
console.log(JSON.stringify(users));
getThreads
but with auth (this will return more data)let data = await threadsAPI.getThreadsLoggedIn(postID);
console.log(JSON.stringify(data.containing_thread));
console.log(JSON.stringify(data.reply_threads));
console.log(JSON.stringify(data.subling_threads));
if (data.downwards_thread_will_continue) {
const cursor = data.paging_tokens.downward;
data = await threadsAPI.getThreadsLoggedIn(postID, cursor);
}
let data = await threadsAPI.getNotifications(
ThreadsAPI.NotificationFilter.MENTIONS, // {MENTIONS, REPLIES, VERIFIED}
);
if (!data.is_last_page) {
const cursor = data.next_max_id;
data = await threadsAPI.getNotifications(ThreadsAPI.NotificationFilter.MENTIONS, cursor);
}
let data = await threadsAPI.getRecommendedUsers();
console.log(JSON.stringify(data.users)); // ThreadsUser[]
if (data.has_more) {
const cursor = data.paging_token;
data = await threadsAPI.getRecommendedUsers(cursor);
}
const query = 'zuck';
const count = 40; // default value is set to 30
const data = await threadsAPI.searchUsers(query, count);
console.log(JSON.stringify(data.num_results));
console.log(JSON.stringify(data.users)); // ThreadsUser[]
Note
From v1.4.0, you can also calllogin
to update yourtoken
anduserID
(for current credentials). Or you can just use the methods below, and they'll take care of the authentication automatically (e.g. if it's the first time you're using those).
import { ThreadsAPI } from 'threads-api';
const main = async () => {
const threadsAPI = new ThreadsAPI({
username: '_junhoyeo', // Your username
password: 'PASSWORD', // Your password
});
await threadsAPI.publish({
text: '🤖 Hello World',
});
};
main();
💡 TIP: Use the
url
field inThreadsAPIPublishOptions
to render Link Attachments(link previews).
await threadsAPI.publish({
text: '🤖 Threads with Reply Control',
replyControl: 'accounts_you_follow', // 'everyone' | 'accounts_you_follow' | 'mentioned_only'
});
await threadsAPI.publish({
text: '🤖 Threads with Link Attachment',
attachment: {
url: 'https://github.com/junhoyeo/threads-api',
},
});
await threadsAPI.publish({
text: '🤖 Threads with Image',
attachment: {
image: 'https://github.com/junhoyeo/threads-api/raw/main/.github/cover.jpg',
},
});
ThreadsAPI.Image
in attachment.image
can also be type of ThreadsAPI.ExternalImage
or ThreadsAPI.RawImage
.
Info
The term "sidecar" is what Threads uses to represent a group of images and/or videos that share the same post.
await threadsAPI.publish({
text: '🤖 Threads with Sidecar',
attachment: {
sidecar: [
'https://github.com/junhoyeo/threads-api/raw/main/.github/cover.jpg',
'https://github.com/junhoyeo/threads-api/raw/main/.github/cover.jpg',
{ path: './zuck.jpg' }, // ThreadsAPI.ExternalImage
{ type: '.jpg', data: Buffer.from(…) }, // ThreadsAPI.RawImage
],
},
});
const parentURL = 'https://www.threads.net/t/CugF-EjhQ3r';
const parentPostID = threadsAPI.getPostIDfromURL(parentURL); // or use `getPostIDfromThreadID`
await threadsAPI.publish({
text: '🤖 Beep',
link: 'https://github.com/junhoyeo/threads-api',
parentPostID: parentPostID,
});
const threadURL = 'https://www.threads.net/t/CuqbBI8h19H';
const postIDToQuote = threadsAPI.getPostIDfromURL(threadURL); // or use `getPostIDfromThreadID`
await threadsAPI.publish({
text: '🤖 Quote a Thread',
quotedPostID: postIDToQuote,
});
const threadURL = 'https://www.threads.net/t/CugK35fh6u2';
const postIDToLike = threadsAPI.getPostIDfromURL(threadURL); // or use `getPostIDfromThreadID`
// 💡 Uses current credentials
await threadsAPI.like(postIDToLike);
await threadsAPI.unlike(postIDToLike);
const userIDToFollow = await threadsAPI.getUserIDfromUsername('junhoyeo');
// 💡 Uses current credentials
await threadsAPI.follow(userIDToFollow);
await threadsAPI.unfollow(userIDToFollow);
const threadURL = 'https://www.threads.net/t/CugK35fh6u2';
const postIDToRepost = threadsAPI.getPostIDfromURL(threadURL); // or use `getPostIDfromThreadID`
// 💡 Uses current credentials
await threadsAPI.repost(postIDToRepost);
await threadsAPI.unrepost(postIDToRepost);
const postID = await threadsAPI.publish({
text: '🤖 This message will self-destruct in 5 seconds.',
});
await new Promise((resolve) => setTimeout(resolve, 5_000));
await threadsAPI.delete(postID);
const userID = await threadsAPI.getUserIDfromUsername('zuck');
const threadURL = 'https://www.threads.net/t/CugK35fh6u2';
const postID = threadsAPI.getPostIDfromURL(threadURL); // or use `getPostIDfromThreadID`
// 💡 Uses current credentials
// Mute User
await threadsAPI.mute({ userID });
await threadsAPI.unfollow({ userID });
// Mute a Post of User
await threadsAPI.mute({ userID, postID });
await threadsAPI.unfollow({ userID, postID });
const userID = await threadsAPI.getUserIDfromUsername('zuck');
// 💡 Uses current credentials
await threadsAPI.block({ userID });
await threadsAPI.unblock({ userID });
// 💡 Uses current credentials
await threadsAPI.setNotificationsSeen();
image
andurl
options inpublish
await threadsAPI.publish({
text: '🤖 Threads with Image',
image: 'https://github.com/junhoyeo/threads-api/raw/main/.github/cover.jpg',
});
await threadsAPI.publish({
text: '🤖 Threads with Link Attachment',
url: 'https://github.com/junhoyeo/threads-api',
});
Singlestring
argument inpublish
import { ThreadsAPI } from 'threads-api';
const main = async () => {
const threadsAPI = new ThreadsAPI({
username: 'jamel.hammoud', // Your username
password: 'PASSWORD', // Your password
});
await threadsAPI.publish('🤖 Hello World');
};
main();
You can also provide custom deviceID
(Default is android-${(Math.random() * 1e24).toString(36)}
).
const deviceID = `android-${(Math.random() * 1e24).toString(36)}`;
const threadsAPI = new ThreadsAPI({
username: 'jamel.hammoud',
password: 'PASSWORD',
deviceID,
});
yarn add threads-api
# or with npm
npm install threads-api
# or with pnpm
pnpm install threads-api
// or in Deno 🦖
import ThreadsAPI from 'npm:threads-api';
const threadsAPI = new ThreadsAPI.ThreadsAPI({});
314216
) via username(zuck
)3140957200974444958
) via ThreadID(CuW6-7KyXme
) or PostURL(https://www.threads.net/t/CuW6-7KyXme
)threads-api
Add yours by just opening an pull request!
react-threads
: Embed Static Threads in your React/Next.js application.Embed Static Threads in your React/Next.js application. UI components for Meta's Threads. Powered by junhoyeo/threads-api.
Warning
Vercel Deployment is currently sometimes unstable. 🏴☠️
threads-api
CLI (WIP)To use the threads-api
command line interface, run the following command:
$ npx threads-api --help
Usage: threads-api [command] [options]
Options:
-v, --version output the current version
-h, --help display help for command
Commands:
help display help for command
getUserIDfromUsername|userid|uid|id <username> det user ID from username
getUserProfile|userprofile|uprof|up <username> <userId> [stringify] get user profile
getUserProfileThreads|uthreads|ut <username> <userId> [stringify] get user profile threads
getUserProfileReplies|userreplies|ureplies|ur <username> <userId> [stringify] get user profile replies
getPostIDfromURL|postid|pid|p <postURL> get post ID from URL
getThreads|threads|t <postId> [stringify] get threads
getThreadLikers|threadlikers|likers|l <postId> [stringify] get thread likers
threads-card
: Share your Threads profile easilyStrings
: Web-Frontend for Threadsthreads-projects
: Unleashing the power of Meta's Threads.net platform with insightful bots and efficient workflows
thread-count
: Custom status badges for Meta's Threads.net follower countsthread-year-prog-bot
: Bot weaving the fabric of timeMIT © Junho Yeo
If you find this project intriguing, please consider starring it(⭐) or following me on GitHub (I wouldn't say Threads). I code 24/7 and ship mind-breaking things on a regular basis, so your support definitely won't be in vain.
FAQs
Unofficial, Reverse-Engineered Node.js/TypeScript client for Meta's [Threads](https://threads.net).
The npm package threads-api receives a total of 172 weekly downloads. As such, threads-api popularity was classified as not popular.
We found that threads-api demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Deno 2.2 enhances Node.js compatibility, improves dependency management, adds OpenTelemetry support, and expands linting and task automation for developers.
Security News
React's CRA deprecation announcement sparked community criticism over framework recommendations, leading to quick updates acknowledging build tools like Vite as valid alternatives.
Security News
Ransomware payment rates hit an all-time low in 2024 as law enforcement crackdowns, stronger defenses, and shifting policies make attacks riskier and less profitable.