Scraper for TikTok. Download videos, music, fetch users info and more.

Overview

tiktok-scraper

A fast light-weight scraper for tiktok to fetch and download video posts, video music, user info and more.

Installation

npm i tiktok-scraper-ts

Importing

TypeScript

import * as tiktokscraper from "tiktok-scraper-ts";

import { TTScraper } from "tiktok-scraper-ts"; // Individual classes

JavaScript

const tiktokscraper = require("tiktok-scraper-ts");

const { TTScraper } = require("tiktok-scraper-ts"); // Individual classes

Methods

.video(url) scrapes video info and download link. Returns Promise<Video>
.user(username) Scrapes user info. Returns Promise<User>
.getAllVideosFromUser(username) Scrapes all available videos for the given user. Returns Promise<IVideo[]>
.getMusic(url) Scrapes Music info from a video. Returns Promise<Music>
.downloadAllVideosFromUser(username, path?: optional) Downloads all Videos of the given user. Returns Promise<void>
.noWaterMark(link) Returns a direct download link for the video without TikTok Watermark.

Examples

Fetch info for a single video

import { TTScraper } from "tiktok-scraper-ts";

const TikTokScraper = new TTScraper();

(async () => {
  const fetchVideo = await TikTokScraper.video("link");
  console.log(fetchVideo);
})();

// ==>

Video {
  id: '7049800036758080773',
  description: undefined,
  createdAt: '05/01/2022',
  height: 1024,
  width: 576,
  duration: 10,
  resolution: '720p',
  shareCount: 12400,
  likesCount: 554500,
  commentCount: 7535,
  playCount: 5500000,
  cover: '',
  playURL: 'PLAY LINK',
  downloadURL: 'Download Link',
  fomrat: 'mp4'
}

Fetch user page

import { TTScraper } from "tiktok-scraper-ts";

const TikTokScraper = new TTScraper();

(async () => {
  const fetchUser = await TikTokScraper.user("user");
  console.log(fetchUser);
})();

// ==>

User {
  id: '',
  uniqueId: 'user',
  nickname: 'new user',
  avatar: 'PP Link',
  signature: '',
  createdAt: '12/12/2021',
  verified: false,
  secretUID: 'MS4wLjABAAAAkLv5v2jUnsIzViWXSAQoj5U4o685FeSDFSDfsdfsdflrk-k75Znw',
  bioLink: undefined,
  privateAccount: false,
  isUnderAge18: false,
  followers: 1,
  following: 2,
  hearts: 0,
  videos: 0
}

Common Types

IUser
export interface IUser {
  /**
   * the id of the User
   */
  id: string;
  /**
   * The tiktok unique id of the User
   */
  uniqueId: string;
  /**
   * optional nickname of the User
   */
  nickname: string;
  /**
   * the avatar link of the User
   */
  avatar: string;
  /**
   * the bio description of the User
   */
  signature: string;
  /**
   * the date of the creation of the User
   */
  createdAt: string;
  /**
   * Whether the User is a verified User by TikTok
   */
  verified: boolean;
  /**
   * the secret UID of the User
   */
  secretUID: string;
  /**
   * The link in the bio if the it contains any
   */
  bioLink: string;
  /**
   * Whether the account privacy is set to private
   */
  privateAccount: boolean;
  /**
   * Whether the User is underage
   */
  isUnderAge18: boolean;
  /**
   * Number of followers for this User
   */
  followers: number;
  /**
   * Number of the accounts this user follows
   */
  following: number;
  /**
   * How many likes this User got over the time
   */
  hearts: number;
  /**
   * Number of the Videos this User has posted
   */
  videos: number;
}
IVideo
export interface IVideo {
  /**
   * the unique id of the video
   */
  id: string;
  /**
   * the description of the video if available
   */
  description: string;
  /**
   * the date on which the video was created on tiktok
   */
  createdAt: string;
  /**
   * height of the video
   */
  height: number;
  /**
   * width of the video
   */
  width: number;
  /**
   * duration of the video
   */
  duration: number;
  /**
   * resolution of the video
   */
  resolution: string;
  /**
   * Number of times the video was shared
   */
  shareCount: number;
  /**
   * Number of likes on the video
   */
  likesCount: number;
  /**
   * Number of comments on the video
   */
  commentCount: number;
  /**
   * Number of times the video has been played
   */
  playCount: number;
  /**
   * a direct url to the video cover
   */
  cover?: string;
  /**
   * A direct url to the dynamic video cover
   */
  dynamicCover?: string;
  /**
   * a direct play url for the video
   */
  playURL?: string;
  /**
   * a direct download url for the video
   */
  downloadURL?: string;
  /**
   * the format of the video
   */
  fomrat?: string;
}
IMusic
export interface IMusic {
  /**
   * tiktok music ic
   */
  id: number;
  /**
   * tiktok music title
   */
  title: string;
  /**
   * direct link to this music
   */
  playURL: string;
  /**
   * tiktok music original cover
   */
  coverLarge: string;
  /**
   * tiktok music thumnail cover
   */
  coverThumb: string;
  /**
   * tiktok music author
   */
  author: string;
  /**
   * tiktok music duration
   */
  duration: number;
  /**
   * Whether the music is original or user made
   */
  original?: boolean;
  /**
   * The Album name if it is part of an album
   */
  album?: string;
}

Contributions

Software contributions are welcome. If you are not a dev, testing and reproting bugs can also be very helpful!

Questions?

Please open an issue if you have questions, wish to request a feature, etc.

Comments
  • Getting  error when  get user by username

    Getting error when get user by username

    /Users/peldam/Documents/tiktok-api/node_modules/tiktok-scraper-ts/dist/main.js:1 var W=Object.create;var f=Object.defineProperty;var O=Object.getOwnPropertyDescriptor;var _=Object.getOwnPropertyNames;var q=Object.getPrototypeOf,D=Object.prototype.hasOwnProperty;var U=o=>f(o,"__esModule",{value:!0}),a=(o,r)=>f(o,"name",{value:r,configurable:!0});var j=(o,r)=>{for(var n in r)f(o,n,{get:r[n],enumerable:!0})},$=(o,r,n,s)=>{if(r&&typeof r=="object"||typeof r=="function")for(let e of _(r))!D.call(o,e)&&(n||e!=="default")&&f(o,e,{get:()=>r[e],enumerable:!(s=O(r,e))||s.enumerable});return o},v=(o,r)=>$(U(f(o!=null?W(q(o)):{},"default",!r&&o&&o.__esModule?{get:()=>o.default,enumerable:!0}:{value:o,enumerable:!0})),o),J=(o=>(r,n)=>o&&o.get(r)||(n=$(U({}),r,1),o&&o.set(r,n),n))(typeof WeakMap!="undefined"?new WeakMap:0);var z={};j(z,{Music:()=>p,TTScraper:()=>m,TikTokResult:()=>b,User:()=>I,Video:()=>g,fetchAllVideosFromUser:()=>P,fetchMusic:()=>F,fetchUser:()=>G,fetchVideo:()=>Y,fetchVideoNoWaterMark:()=>H,hashtag:()=>K});var L=v(require("cheerio")),x=v(require("miniget")),T=v(require("node-fetch")),l=require("fs"),S=v(require("http")),E=v(require("https")),R=require("process");var I=class{constructor(r,n,s,e,t,u,i,h,c,w,M,k,A,C,y){this.id=r,this.uniqueId=n,this.nickname=s,this.avatar=e,this.signature=t,this.createdAt=u,this.verified=i,this.secretUID=h,this.bioLink=c,this.privateAccount=w,this.isUnderAge18=M,this.followers=k,this.following=A,this.hearts=C,this.videos=y}};a(I,"User");var b=class{constructor(r,n,s,e,t,u,i,h,c,w){this.author=r,this.video=n,this.audio=s,this.shareCount=e,this.likesCount=t,this.commentCount=u,this.playCount=i,this.createdAt=h,this.tiktokLink=c,this.thumbnail=w}};a(b,"TikTokResult");var g=class{constructor(r,n,s,e,t,u,i,h,c,w,M,k,A,C,y,V,N){this.id=r,this.description=n,this.createdAt=s,this.height=e,this.width=t,this.duration=u,this.resolution=i,this.shareCount=h,this.likesCount=c,this.commentCount=w,this.playCount=M,this.downloadURL=k,this.cover=A,this.dynamicCover=C,this.playURL=y,this.format=V,this.author=N}};a(g,"Video");var p=class{constructor(r,n,s,e,t,u,i,h,c){this.id=r,this.title=n,this.playURL=s,this.coverLarge=e,this.coverThumb=t,this.author=u,this.duration=i,this.original=h,this.album=c}};a(p,"Music");var m=class{async requestWebsite(r,n){let s=new S.default.Agent({keepAlive:!0,maxSockets:20}),e=new E.default.Agent({keepAlive:!0,maxSockets:20}),t={agent:c=>c.protocol=="http:"?s:e,headers:{"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36 Edg/97.0.1072.62"}},i=await(await(0,T.default)(${r},n||t)).text();return L.load(i,{xmlMode:!0})}handleHTMLContent(r){let n=r,s=n.split("window['SIGI_STATE']=")[1].indexOf(";window['SIGI_RETRY']=");return JSON.parse(n.split("window['SIGI_STATE']=")[1].slice(0,s))}async video(r){if(!r)throw new Error("A video URL must be provided");let s=(await this.requestWebsite(r))("#SIGI_STATE").text(),e=JSON.parse(s),t=e.ItemList.video.list[0];return new g(e.ItemModule[t].video.id,e.ItemModule[t].desc,new Date(Number(e.ItemModule[t].createTime)1e3).toLocaleDateString(),Number(e.ItemModule[t].video.height),Number(e.ItemModule[t].video.width),Number(e.ItemModule[t].video.duration),e.ItemModule[t].video.ratio,e.ItemModule[t].stats.shareCount,e.ItemModule[t].stats.diggCount,e.ItemModule[t].stats.commentCount,e.ItemModule[t].stats.playCount,e.ItemModule[t].video.downloadAddr.trim(),e.ItemModule[t].video.cover,e.ItemModule[t].video.dynamicCover,e.ItemModule[t].video.playAddr.trim(),e.ItemModule[t].video.format,e.ItemModule[t].nickname)}async user(r){if(!r)throw new Error("Please enter a username");let s=(await this.requestWebsite(https://www.tiktok.com/@${r}))("#SIGI_STATE").text(),e=JSON.parse(s),t=e.UserModule.users[r];return new I(t.id,t.uniqueId,t.nickname,t.avatarLarger,t.signature.trim(),new Date(t.createTime1e3).toLocaleDateString(),t.verified,t.secUid,t?.bioLink?.link,t.privateAccount,t.isUnderAge18,e.UserModule.stats[r].followerCount,e.UserModule.stats[r].followingCount,e.UserModule.stats[r].heart,e.UserModule.stats[r].videoCount)}async getAllVideosFromUser(r){if(!r)throw new Error("You must provide a username!");let s=(await this.requestWebsite(https://www.tiktok.com/@${r}))("#SIGI_STATE").text(),e=JSON.parse(s),t=[],{ItemList:u}=e;return u["user-post"].list.forEach(i=>{t.push(new g(e.ItemModule[i].video.id,e.ItemModule[i].desc,new Date(Number(e.ItemModule[i].createTime)*1e3).toLocaleDateString(),Number(e.ItemModule[i].video.height),Number(e.ItemModule[i].video.width),Number(e.ItemModule[i].video.duration),e.ItemModule[i].video.ratio,e.ItemModule[i].stats.shareCount,e.ItemModule[i].stats.diggCount,e.ItemModule[i].stats.commentCount,e.ItemModule[i].stats.playCount,e.ItemModule[i].video.downloadAddr.trim(),e.ItemModule[i].video.cover,e.ItemModule[i].video.dynamicCover,e.ItemModule[i].video.playAddr.trim(),e.ItemModule[i].video.format))}),t}async getMusic(r){if(!r)throw new Error("You must provide a link!");let s=(await this.requestWebsite(r))("#SIGI_STATE").text(),e=JSON.parse(s),t=e.ItemList.video.list[0];return new p(e.ItemModule[t].music.id,e.ItemModule[t].music.title,e.ItemModule[t].music.playUrl,e.ItemModule[t].music.coverLarge,e.ItemModule[t].music.coverThumb,e.ItemModule[t].music.authorName,Number(e.ItemModule[t].music.duration),e.ItemModule[t].music.original,e.ItemModule[t].music.album)}async downloadAllVideosFromUser(r,n){if(!r)throw new Error("Please enter a username!");let s=await this.getAllVideosFromUser(r);if(!s)throw new Error("No Videos were found for this username. Either the videos are private or the user has not videos");if(!n.path){if(n.path=${__dirname}/../${r},(0,l.existsSync)(n.path)){console.log("A folder with this username exists, that is unusual!");try{(0,l.unlinkSync)(n.path)}catch(e){console.log(`[ERROR] Could not remove ${n.path} ^ SyntaxError: Unexpected end of JSON input at JSON.parse () at m.user (/Users/peldam/Documents/tiktok-api/node_modules/tiktok-scraper-ts/dist/main.js:1:3703) at processTicksAndRejections (node:internal/process/task_queues:95:5) at Object.fetchUser (/Users/peldam/Documents/tiktok-api/node_modules/tiktok-scraper-ts/dist/main.js:2:2253)

    opened by pelldam 7
  • `getAllVideosFromUser` function only fetch maximum 30 videos

    `getAllVideosFromUser` function only fetch maximum 30 videos

    First of all, I wanna say thank you for your API it's amazing, almost function working perfectly except getAllVideosFromUser getAllVideosFromUser function only fetches a maximum of 30 videos, can we have a solution to fetch all videos of a user? I research before we need some signature and an endpoint for that

    bug duplicate enhancement 
    opened by tonyquang 7
  • Error JSON input

    Error JSON input

    can you help me in solving my problem?, I have a problem, namely SyntaxError: Unexpected end of JSON input

    what should i do, i just learned about all of this

    opened by Mukclay 1
  • Feature : scrap hashtag posts

    Feature : scrap hashtag posts

    Hi,

    Thank you a lot for this tiktok scraper working very well and very simple to use.

    Is it possible to add the possibility to scrap hashtags ?

    Thank you

    enhancement 
    opened by Spawnrad 1
  • get and downloadAllVideosFromUser only returning the most recent 30 videos?

    get and downloadAllVideosFromUser only returning the most recent 30 videos?

    Hi, the scraper works well!

    When I use the getAllVideosFromUser and downloadAllVideosFromUser methods, it only returns the 30 most recent videos from the profile.

    Is there something I'm doing wrong, or is its a limitation imposed by the scraper/language/TikTok, or something else?

    Thanks

    wontfix 
    opened by aa1s2d 1
  • Have no permission to the video's URL

    Have no permission to the video's URL

    I got the URL to get the video but got an error. If I open this link I get an Error: You don't have permission to access "http://v16-webapp-prime.tiktok.com.....

    opened by VladisB 0
  • Hashtag Videos By CreatedAt

    Hashtag Videos By CreatedAt

    I want to retrieve videos from hashtag function but there isn't any option for how many videos I'll receive or by their created time. Are these options available? Can you make something like that?

    opened by karatayburak 0
  • "Unexpected end of JSON input" When trying to get all videos from a user ...

    Hello,

    I've tried anything that I can, but I am never able to get all videos from a user ...

    I always have this error : invalid json response body at https://api2.musical.ly/aweme/v1/aweme/detail/?aweme_id=7144372530571267333 reason: Unexpected end of JSON input. type: 'invalid-json';

    This is my code :

    app.get('/getAllVideos', async (req, res) => {
      var username = "exclutele";
      const videos = await tiktokscraper.getAllVideosFromUser(username,true);
      res.send(videos);
      console.log(videos);
    });
    

    Can you help me to figure it out ?

    Thanks !

    opened by palmthree-studio 5
Owner
"Never theorize before you have data. Invariably, you end up twisting facts to suit theories instead of theories to suit facts." Sherlock Holmes
null
Recap let's you recap on your favourite social network videos by downloading them on your devices, from the range of YouTube, SoundCloud, Facebook, Twitter, Instagram, TikTok, Vimeo, Dailymotion, VK, or AOL.

Recap A Social Network Video Downloader Recap let's you recap on your favourite social network videos by downloading them on your devices, from the ra

John Oladele 4 Sep 24, 2022
Advanced Music Bot It is an advance type of discord music bot which plays high quality of music with spotify

Advanced Music Bot It is an advance type of discord music bot which plays high quality of music with spotify, apple music support . You can save your songs and play it. It also has DJ mode system.

Diwas Atreya 65 Dec 25, 2022
A decentralized Music Ownership System developed on Truffle Suite and React Bootstrap to allow Music artists to upload their content to the blockchain, that can be streamed by users

A decentralized Music Ownership System developed on Truffle Suite and React Bootstrap to allow Music artists to upload their content to the blockchain, that can be streamed by users.

M. Adil Fayyaz 10 Sep 5, 2022
A tool to download all videos and convert to mp3 inside a video set of bilibili.

bilibili-video2mp3 A tool to download all videos and convert to mp3 inside a video set of bilibili (also works for single video, of course). You will

wxsm 23 Dec 15, 2022
A simple package to download music tracks from spotify ๐ŸŽต

A simple package to download music tracks from spotify ??

Alen Yohannan 26 Dec 25, 2022
Rebuilding TikTok with api.video, PWA, Next.js and Typescript ๐ŸŽต

Rebuilding TikTok with api.video, PWA, Next.js and Typescript ?? An open-source example application that allows users to list and upload videos in the

api.video 3 Jul 1, 2022
Music-Player - Music player application built with HTML, CSS and vanilla JavaScript

Music-Player Music player application built with HTML, CSS and vanilla JavaScrip

Karthik Umashankar 1 Feb 10, 2022
Iโ€™m a very useful music bot that can make you play a music with a simple command! I have a lot of good commands that you can have a better experience playing your favorites songs!

Iโ€™m a very useful music bot that can make you play a music with a simple command! I have a lot of good commands that you can have a better experience playing your favorites songs!

Hugo Kishi 2 Aug 16, 2022
A mobile app for playing music on Resonate, an open source music streaming co-op.

stream2own Play fair. Website | Twitter | Contributing | Developer Guide ?? Resonate Stream App A mobile app for playing music on Resonate, an open so

Peter Klingelhofer 12 Dec 28, 2022
A multi-purpose discord bot, that has 100+ commands. Includes ๐ŸŽถ Music, ๐Ÿ“ท Image Generation, ๐Ÿ“Š Leaderboard, and more!

Cleckzie An open-source, multi-purpose discord bot, made with JavaScript. Has useful categories like: ?? Music - filter, seek, queue, volume and more.

null 42 Jul 2, 2022
ALi a powerful Discord bot that includes Utility, Fun, Music, Moderation, and much more! (Beta)

ALi ALi a powerful Discord Bot Invite ALi ยท Report Bug ยท Request Feature ?? Futures Music Moderation Fun Economy Utility More ?? Installation You can

S Dip 97 Oct 17, 2022
Tritan is a Discord.js bot that has many general-purpose features such as logging, moderation, image manipulation, music, and much more!

Tritan Bot Tritan Bot is a Discord Verified general purpose bot built with discord.js and express (yes, it has a dashboard included). Please read thro

Dylan J. 0 Jul 3, 2022
Tritan is a Discord.js bot that has many general-purpose features such as logging, moderation, image manipulation, music, and much more!

Tritan Bot Tritan Bot is a Discord Verified general purpose bot built with discord.js and express (yes, it has a dashboard included). Please read thro

Team Tritan 5 Nov 19, 2022
A NodeJS package for voice channel interactions on Revolt. This package lets you join voice channels, play music and more!

Revoice.js - A Voice Module for Revolt This package is still in developement and lacks many features. You still are able to play sound to a voice chan

ShadowLp174 13 Dec 25, 2022
A Discord bot to fetch random waifu images

Waifu Discord Bot A Discord bot to fetch random waifu images! Commands -waifu - To fetch image Config Vars TOKEN - Your Discord bot token Deploy To Ra

Nisarga Adhikary 9 Dec 19, 2022
Compress program that uses H264,VP9 and Vorbis algorithms with ffmpeg to compress anime videos and audios

Vaniply Compress tool to compress videos and audios using H264,VP9 and Vorbis algorithms Installation and running Just clone the repository and open a

null 18 Oct 15, 2022
Compress program that uses H264,VP9 and Vorbis algorithms with ffmpeg to compress anime videos and audios

Vaniply Compress tool to compress videos and audios using H264,VP9 and Vorbis algorithms Installation and running Just clone the repository and open a

OpenAnime 20 May 30, 2022
Self-Hosted Discord Bot to onboard users, protect users, and gamify entertainment & engagement.

Self-Hosted Open-Source Discord Bot to onboard & protect community members. It gamifies user entertainment & engagement. Usage Clone using: git clone

Accretence 4 Sep 8, 2022
Create videos using React!

Reactive Videos are videos created using HTML and React components. This allows you to leverage the almost limitless possibilities of the web browser

Mikael Finstad 76 Dec 25, 2022