npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

threads-api-ai

v1.1.0

Published

A Node.js client library for the Facebook Threads API with TypeScript support

Readme

threads-api-ai

A Node.js client library for the Facebook Threads API with full TypeScript support.

Features

  • OAuth 2.0 Authentication - Complete authentication flow with short-lived and long-lived tokens
  • User Profile API - Get user profile information and threads
  • Publishing API - Create and publish text, image, video, and carousel posts
  • TypeScript Support - Full type definitions for all API methods
  • Promise-based - Modern async/await API
  • Error Handling - Comprehensive error handling with detailed messages
  • 🚧 More features coming soon - Insights, replies, webhooks, and more

Installation

npm install threads-api-ai

Prerequisites

Before using this library, you need to:

  1. Create a Threads app in the Meta Developer Portal
  2. Get your App ID and App Secret
  3. Configure OAuth redirect URI in your app settings
  4. Request necessary permissions/scopes

Quick Start

import ThreadsAPI from 'threads-api-ai';

// Initialize the client
const client = new ThreadsAPI({
  appId: 'YOUR_APP_ID',
  appSecret: 'YOUR_APP_SECRET',
  redirectUri: 'https://yourapp.com/callback'
});

// Step 1: Generate authorization URL
const authUrl = client.auth.getAuthorizationUrl([
  'threads_basic',
  'threads_content_publish'
], 'optional-state-for-csrf');

console.log('Visit this URL to authorize:', authUrl);

// Step 2: After user authorizes, exchange code for tokens
const code = 'CODE_FROM_CALLBACK';
const tokens = await client.auth.completeAuthFlow(code);

console.log('Access Token:', tokens.access_token);
console.log('Expires in:', tokens.expires_in, 'seconds');

Authentication Guide

The Threads API uses OAuth 2.0 for authentication. This library provides methods for the complete authentication flow.

Available Scopes

  • threads_basic - Read basic profile information
  • threads_content_publish - Publish content on behalf of the user
  • threads_manage_insights - Read insights and analytics
  • threads_manage_replies - Manage replies to posts
  • threads_read_replies - Read replies to posts

Complete Authentication Flow

import ThreadsAPI from 'threads-api-ai';

const client = new ThreadsAPI({
  appId: process.env.THREADS_APP_ID!,
  appSecret: process.env.THREADS_APP_SECRET!,
  redirectUri: 'https://yourapp.com/auth/callback'
});

// 1. Generate authorization URL
const authUrl = client.auth.getAuthorizationUrl([
  'threads_basic',
  'threads_content_publish'
], 'your-random-state-string');

// Redirect user to authUrl...
// User authorizes and is redirected back to your callback URL with a code

// 2. Exchange code for tokens (this method handles both short and long-lived tokens)
const tokens = await client.auth.completeAuthFlow(code);

// Save tokens.access_token securely - it's valid for ~60 days

Manual Token Exchange

If you prefer to handle the token exchange manually:

// Get short-lived token (valid for ~1 hour)
const shortToken = await client.auth.getAccessToken(code);

// Exchange for long-lived token (valid for ~60 days)
const longToken = await client.auth.getLongLivedToken(shortToken.access_token);

Refreshing Long-Lived Tokens

Long-lived tokens expire after ~60 days. Refresh them before they expire:

const refreshedToken = await client.auth.refreshLongLivedToken(
  currentLongLivedToken
);

// Save the new token - it's valid for another ~60 days

Express.js Example

Here's a complete example using Express.js:

import express from 'express';
import ThreadsAPI from 'threads-api-ai';

const app = express();

const client = new ThreadsAPI({
  appId: process.env.THREADS_APP_ID!,
  appSecret: process.env.THREADS_APP_SECRET!,
  redirectUri: 'http://localhost:3000/auth/callback'
});

// Route to initiate OAuth
app.get('/auth/threads', (req, res) => {
  const authUrl = client.auth.getAuthorizationUrl([
    'threads_basic',
    'threads_content_publish'
  ], req.session.state); // Use session-based state for security
  
  res.redirect(authUrl);
});

// OAuth callback route
app.get('/auth/callback', async (req, res) => {
  try {
    const { code, state } = req.query;
    
    // Verify state matches (CSRF protection)
    if (state !== req.session.state) {
      throw new Error('State mismatch');
    }
    
    // Complete auth flow and get long-lived token
    const tokens = await client.auth.completeAuthFlow(code as string);
    
    // Save tokens securely (e.g., in database)
    req.session.accessToken = tokens.access_token;
    
    res.send('Authentication successful!');
  } catch (error) {
    console.error('Auth error:', error);
    res.status(500).send('Authentication failed');
  }
});

app.listen(3000);

User Profile API

Once you have an access token, you can retrieve user profile information and threads.

Get User Profile

// Get the authenticated user's profile
const profile = await client.profile.getProfile(accessToken);

console.log('User ID:', profile.id);
console.log('Username:', profile.username);
console.log('Profile Picture:', profile.threads_profile_picture_url);
console.log('Bio:', profile.threads_biography);

// Get specific fields only
const customProfile = await client.profile.getProfile(
  accessToken,
  ['id', 'username'] // Only fetch these fields
);

Get User's Threads

// Get the authenticated user's threads
const threads = await client.profile.getUserThreads(accessToken);

console.log('User threads:', threads.data);

// Get threads with custom fields and limit
const customThreads = await client.profile.getUserThreads(
  accessToken,
  'me', // or specific user ID
  ['id', 'text', 'permalink', 'timestamp'], // fields to retrieve
  10 // limit
);

Get Single Thread

// Get a specific thread by ID
const thread = await client.profile.getThread(accessToken, 'THREAD_ID');

console.log('Thread text:', thread.text);
console.log('Permalink:', thread.permalink);
console.log('Media URL:', thread.media_url);

Publishing API

Create and publish text posts, images, videos, and carousels.

Publish a Text Post

// Simple text post (all in one step)
const result = await client.publishing.createAndPublishThread(
  accessToken,
  'me',
  {
    media_type: 'TEXT',
    text: 'Hello from Threads API! 👋'
  }
);

console.log('Published thread ID:', result.id);

Publish an Image Post

// Post with image
const imagePost = await client.publishing.createAndPublishThread(
  accessToken,
  'me',
  {
    media_type: 'IMAGE',
    image_url: 'https://example.com/image.jpg',
    text: 'Check out this image!'
  }
);

Publish a Video Post

// Post with video
const videoPost = await client.publishing.createAndPublishThread(
  accessToken,
  'me',
  {
    media_type: 'VIDEO',
    video_url: 'https://example.com/video.mp4',
    text: 'Watch this video!'
  }
);

Publish a Carousel Post

// Create carousel items first
const item1 = await client.publishing.createCarouselItem(
  accessToken,
  'me',
  { image_url: 'https://example.com/image1.jpg' }
);

const item2 = await client.publishing.createCarouselItem(
  accessToken,
  'me',
  { image_url: 'https://example.com/image2.jpg' }
);

// Create and publish carousel
const carousel = await client.publishing.createAndPublishThread(
  accessToken,
  'me',
  {
    media_type: 'CAROUSEL',
    carousel_item_ids: [item1.id, item2.id],
    text: 'Swipe to see more!'
  }
);

Reply to a Thread

// Reply to another thread
const reply = await client.publishing.createAndPublishThread(
  accessToken,
  'me',
  {
    media_type: 'TEXT',
    text: 'This is a reply!',
    reply_to_id: 'PARENT_THREAD_ID'
  }
);

Control Who Can Reply

// Control reply permissions
const post = await client.publishing.createAndPublishThread(
  accessToken,
  'me',
  {
    media_type: 'TEXT',
    text: 'Only people I follow can reply',
    reply_control: 'accounts_you_follow' // or 'everyone' or 'mentioned_only'
  }
);

Manual Two-Step Publishing

If you need more control, you can manually create and publish in two steps:

// Step 1: Create thread container
const container = await client.publishing.createThread(
  accessToken,
  'me',
  {
    media_type: 'TEXT',
    text: 'My post'
  }
);

// Step 2: Publish the container
const published = await client.publishing.publishThread(
  accessToken,
  'me',
  {
    creation_id: container.id
  }
);

console.log('Published thread ID:', published.id);

Check Publishing Limits

// Get publishing rate limit info
const limits = await client.publishing.getPublishingLimit(accessToken);

console.log('Quota usage:', limits.data);

Error Handling

The library throws detailed errors with API error codes and messages:

try {
  const tokens = await client.auth.getAccessToken(code);
} catch (error) {
  console.error(error.message);
  // Example: "Threads API Error (190): Invalid OAuth access token"
}

API Reference

ThreadsAPI

Main client class.

Constructor

new ThreadsAPI(config: ThreadsAPIConfig)

Parameters:

  • config.appId (string) - Your Threads App ID
  • config.appSecret (string) - Your Threads App Secret
  • config.redirectUri (string) - OAuth redirect URI
  • config.apiVersion (string, optional) - API version (default: 'v1.0')

Properties

  • auth - Authentication handler
  • profile - User profile handler
  • publishing - Publishing handler

ThreadsAuth

Authentication handler (accessible via client.auth).

Methods

getAuthorizationUrl(scopes, state?)

Generate OAuth authorization URL.

Parameters:

  • scopes (ThreadsScope[]) - Array of permission scopes
  • state (string, optional) - State parameter for CSRF protection

Returns: Authorization URL (string)

getAccessToken(code)

Exchange authorization code for short-lived access token.

Parameters:

  • code (string) - Authorization code from callback

Returns: Promise

getLongLivedToken(shortLivedToken)

Exchange short-lived token for long-lived token.

Parameters:

  • shortLivedToken (string) - Short-lived access token

Returns: Promise

refreshLongLivedToken(longLivedToken)

Refresh a long-lived token.

Parameters:

  • longLivedToken (string) - Current long-lived token

Returns: Promise

completeAuthFlow(code)

Complete full OAuth flow (recommended method).

Parameters:

  • code (string) - Authorization code from callback

Returns: Promise

ThreadsProfile

User profile handler (accessible via client.profile).

Methods

getProfile(accessToken, fields?)

Get the authenticated user's profile.

Parameters:

  • accessToken (string) - User's access token
  • fields (string[], optional) - Fields to retrieve (default: id, username, threads_profile_picture_url, threads_biography)

Returns: Promise

getUserThreads(accessToken, userId?, fields?, limit?)

Get a user's threads.

Parameters:

  • accessToken (string) - User's access token
  • userId (string, optional) - User ID (default: 'me')
  • fields (string[], optional) - Fields to retrieve
  • limit (number, optional) - Number of threads (default: 25, max: 100)

Returns: Promise

getThread(accessToken, threadId, fields?)

Get a specific thread by ID.

Parameters:

  • accessToken (string) - User's access token
  • threadId (string) - Thread ID
  • fields (string[], optional) - Fields to retrieve

Returns: Promise

ThreadsPublishing

Publishing handler (accessible via client.publishing).

Methods

createThread(accessToken, userId, params)

Create a thread container (step 1 of publishing).

Parameters:

  • accessToken (string) - User's access token
  • userId (string) - User ID (default: 'me')
  • params (CreateThreadParams) - Thread creation parameters

Returns: Promise

publishThread(accessToken, userId, params)

Publish a thread container (step 2 of publishing).

Parameters:

  • accessToken (string) - User's access token
  • userId (string) - User ID (default: 'me')
  • params (PublishThreadParams) - Publishing parameters

Returns: Promise

createAndPublishThread(accessToken, userId, params)

Create and publish a thread in one step (convenience method).

Parameters:

  • accessToken (string) - User's access token
  • userId (string) - User ID (default: 'me')
  • params (CreateThreadParams) - Thread creation parameters

Returns: Promise

createCarouselItem(accessToken, userId, params)

Create a carousel item for carousel posts.

Parameters:

  • accessToken (string) - User's access token
  • userId (string) - User ID (default: 'me')
  • params (CreateCarouselItemParams) - Carousel item parameters

Returns: Promise

getPublishingLimit(accessToken, userId?)

Get the publishing limit for the user.

Parameters:

  • accessToken (string) - User's access token
  • userId (string, optional) - User ID (default: 'me')

Returns: Promise

TypeScript Types

All types are exported and available for use:

import { 
  ThreadsAPIConfig,
  ThreadsScope,
  AccessTokenResponse,
  LongLivedTokenResponse,
  RefreshTokenResponse,
  ThreadsUserProfile,
  MediaType,
  CreateThreadParams,
  CreateThreadResponse,
  PublishThreadParams,
  PublishThreadResponse,
  CreateCarouselItemParams,
  Thread
} from 'threads-api-ai';

Roadmap

  • [x] OAuth 2.0 Authentication
  • [x] User Profile API
  • [x] Publishing API (create posts)
    • [x] Text posts
    • [x] Image posts
    • [x] Video posts
    • [x] Carousel posts
    • [x] Reply control
    • [x] Publishing limits
  • [ ] Media API (upload images/videos)
  • [ ] Insights API (analytics)
  • [ ] Replies API (manage comments)
  • [ ] Webhooks support

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

MIT

Support

For issues and questions, please use the GitHub Issues page.

Disclaimer

This is an unofficial library and is not affiliated with Meta Platforms, Inc.

Resources