TikTokDownload API接口全解析:开发者必备参考

TikTokDownload API接口全解析:开发者必备参考

【免费下载链接】TikTokDownload 抖音去水印批量下载用户主页作品、喜欢、收藏、图文、音频 【免费下载链接】TikTokDownload 项目地址: https://gitcode.com/gh_mirrors/ti/TikTokDownload

你是否还在为抖音(TikTok)内容批量下载的复杂流程而困扰?是否因API接口文档缺失而无法高效开发?本文将系统解析TikTokDownload项目的API接口体系,从用户信息获取到作品批量下载,从参数配置到错误处理,提供一站式解决方案。读完本文,你将获得:

  • 7个核心API接口的详细调用指南
  • 10+实用参数配置技巧
  • 完整的错误码对照表
  • 3种语言的调用示例代码
  • 高并发场景的性能优化方案

项目概述

TikTokDownload是一个专注于抖音内容去水印批量下载的开源项目,支持用户主页作品、喜欢、收藏、图文、音频等多种资源类型的获取。其API接口体系基于RESTful设计规范,提供了简洁易用的接口调用方式,开发者可快速集成到自己的应用中。

mermaid

API接口详解

1. 用户基本信息接口

接口路径/API/user_base_info.json
请求方法:GET
功能描述:获取指定用户的基本信息,包括头像、昵称、签名、关注状态等核心数据。

请求参数

参数名类型必选描述示例值
sec_uidstring用户安全IDMS4wLjABAAAADgOltsr_SYTX6VurKA1H3n61xlFvYD1y_FrrY1UhI-o
unique_idstring用户唯一ID777_23

响应示例

{
  "status_code": 0,
  "data": [
    {
      "uid": "89964046416",
      "short_id": "629064951",
      "nickname": "蔓越莓烦恼",
      "avatar_thumb": {
        "uri": "100x100/aweme-avatar/tos-cn-avt-0015_9c8aea4ba21f591774723a3820a07aef",
        "url_list": [
          "https://p3.douyinpic.com/aweme/100x100/aweme-avatar/tos-cn-avt-0015_9c8aea4ba21f591774723a3820a07aef.jpeg?from=3782654143",
          "https://p6.douyinpic.com/aweme/100x100/aweme-avatar/tos-cn-avt-0015_9c8aea4ba21f591774723a3820a07aef.jpeg?from=3782654143",
          "https://p11.douyinpic.com/aweme/100x100/aweme-avatar/tos-cn-avt-0015_9c8aea4ba21f591774723a3820a07aef.jpeg?from=3782654143"
        ]
      },
      "signature": "风格多变的小🦁️\n🧣:yoki小蔓\n🍠:同名",
      "follow_status": 1,
      "unique_id": "777_23",
      "sec_uid": "MS4wLjABAAAADgOltsr_SYTX6VurKA1H3n61xlFvYD1y_FrrY1UhI-o"
    }
  ]
}

字段说明

字段名类型描述
uidstring用户数字ID
short_idstring用户短ID
nicknamestring用户昵称
avatar_thumbobject头像缩略图信息
signaturestring用户签名
follow_statusinteger关注状态(0:未关注,1:已关注)
unique_idstring用户唯一ID
sec_uidstring用户安全ID

2. 视频作品信息接口

接口路径/API/user_post_info_video.json
请求方法:GET
功能描述:获取用户发布的视频作品列表,支持分页获取,返回视频的详细信息和下载地址。

请求参数

参数名类型必选描述示例值
sec_uidstring用户安全IDMS4wLjABAAAAdBrGekUlNXGPsc8rNnv_jDhN8koyuWDyrU3CrcvzmcQ
countinteger每页数量,默认2020
cursorinteger分页游标,第一页为00

响应示例

{
  "status_code": 0,
  "min_cursor": 1689909551000,
  "max_cursor": 1689909551000,
  "has_more": 1,
  "aweme_list": [
    {
      "aweme_id": "7253290037918354691",
      "desc": "飞行员跳伞进影视基地,哪知道白捡了个寨主当 #电影冰雪狙击2  #冰雪狙击2老戏骨飙戏",
      "create_time": 1688788818,
      "video": {
        "play_addr": {
          "uri": "v0200fg10000cikdoqjc77u487ia3t1g",
          "url_list": [
            "http://v26-web.douyinvod.com/f09adc21743f08884ebfd18bee2c7757/64ba6b84/video/tos/cn/tos-cn-ve-15c001-alinc2/oMSoq9gqbAIgtxOKQn9keEBD4DACeAMhgNREnI/?a=6383&ch=10010&cr=0&dr=0&lr=all&cd=0|0|0|0&cv=1&br=2198&bt=2198&cs=0&ds=4&ft=bvTKJbQQqUWXf_40mo0OW_EklpPiXwUEiMVJEAmEA.CPD-I&mime_type=video_mp4&qs=0&rc=NzhnOmg5ODc7O2U5ZTVmZ0BpandkOjc6ZnRnbDMzNGkzM0AtX2NeXmJjNl4xLTRfL141YSMuMGY1cjRnbGhgLS1kLS9zcw==&l=202307211825566527AF3C1671F5138610&btag=e00028000&dy_q=1689935156",
            "http://v3-web.douyinvod.com/a5e31e04504bc6463031a9d4036d643d/64ba6b84/video/tos/cn/tos-cn-ve-15c001-alinc2/oMSoq9gqbAIgtxOKQn9keEBD4DACeAMhgNREnI/?a=6383&ch=10010&cr=0&dr=0&lr=all&cd=0|0|0|0&cv=1&br=2198&bt=2198&cs=0&ds=4&ft=bvTKJbQQqUWXf_40mo0OW_EklpPiXwUEiMVJEAmEA.CPD-I&mime_type=video_mp4&qs=0&rc=NzhnOmg5ODc7O2U5ZTVmZ0BpandkOjc6ZnRnbDMzNGkzM0AtX2NeXmJjNl4xLTRfL141YSMuMGY1cjRnbGhgLS1kLS9zcw==&l=202307211825566527AF3C1671F5138610&btag=e00028000&dy_q=1689935156"
          ],
          "width": 1728,
          "height": 1080,
          "data_size": 18025814
        },
        "cover": {
          "uri": "tos-cn-i-dy/bc4a6c96faea452e983b1371561e853d",
          "url_list": [
            "https://p3-pc-sign.douyinpic.com/tos-cn-i-dy/bc4a6c96faea452e983b1371561e853d~tplv-dy-cropcenter:323:430.jpeg?x-expires=1691143200&x-signature=M/mIef2TBxaBIg5VGxQtKuAK/5U=&from=3213915784&s=PackSourceEnum_PUBLISH&se=true&sh=323_430&sc=cover&biz_tag=pcweb_cover&l=202307211825566527AF3C1671F5138610"
          ],
          "width": 720,
          "height": 720
        },
        "height": 1200,
        "width": 1920,
        "ratio": "1080p"
      },
      "statistics": {
        "comment_count": 166,
        "digg_count": 20629,
        "collect_count": 1572,
        "share_count": 406
      }
    }
  ]
}

分页机制

该接口采用游标分页机制,通过cursor参数控制分页位置,has_more字段表示是否还有更多数据。分页流程如下:

mermaid

视频质量选择

接口返回多种清晰度的视频地址,可根据需求选择:

清晰度gear_namebit_rate适用场景
1080Pnormal_1080_02251713高清展示
720Pnormal_720_01444459平衡质量和流量
540Pnormal_540_01305609普通观看
低清lower_540_0872751省流量模式

3. 图文作品信息接口

接口路径/API/user_post_info_image.json
请求方法:GET
功能描述:获取用户发布的图文作品列表,支持分页获取,返回图文的详细信息和图片下载地址。

请求参数

参数名类型必选描述示例值
sec_uidstring用户安全IDMS4wLjABAAAA-hFsLR8fSnbmWhrmAEnGvYgG6rM2txNpNm2oT9WSrIQ
countinteger每页数量,默认2020
cursorinteger分页游标,第一页为00

响应示例

{
  "status_code": 0,
  "min_cursor": 1689909551000,
  "max_cursor": 1689909551000,
  "has_more": 1,
  "aweme_list": [
    {
      "aweme_id": "7232626237586312485",
      "desc": "辣妹统治世界٩(˃̶͈̀௰˂̶͈́)و。#ootd穿搭  #氛围感 #女友穿搭#辣妹穿搭 #生活碎片",
      "create_time": 1683977029,
      "share_url": "https://www.iesdouyin.com/share/video/7232626237586312485/?region=CN&mid=7203284398119225346&u_code=l1j9bkbd",
      "statistics": {
        "comment_count": 166,
        "digg_count": 20629,
        "collect_count": 1572,
        "share_count": 406
      },
      "text_extra": [
        {
          "start": 20,
          "end": 27,
          "type": 1,
          "hashtag_name": "ootd穿搭",
          "hashtag_id": "1645837370349579"
        },
        {
          "start": 29,
          "end": 33,
          "type": 1,
          "hashtag_name": "氛围感",
          "hashtag_id": "1640936621124619"
        }
      ]
    }
  ]
}

4. 作品详情接口

接口路径/API/user_post_detail.json
请求方法:GET
功能描述:获取单个作品的详细信息,包括完整的评论、点赞、分享等互动数据。

请求参数

参数名类型必选描述示例值
aweme_idstring作品ID7253290037918354691

5. 作品删除接口

接口路径/API/user_post_delete.json
请求方法:POST
功能描述:删除用户发布的作品,需要用户授权。

请求参数

参数名类型必选描述示例值
aweme_idstring作品ID7253290037918354691
sec_uidstring用户安全IDMS4wLjABAAAADgOltsr_SYTX6VurKA1H3n61xlFvYD1y_FrrY1UhI-o

接口调用示例

Python调用示例

import requests
import json

def get_user_videos(sec_uid, max_count=50):
    """
    获取用户视频作品列表
    
    :param sec_uid: 用户安全ID
    :param max_count: 最大获取数量
    :return: 视频列表
    """
    videos = []
    cursor = 0
    base_url = "https://api.example.com/API/user_post_info_video.json"
    
    while len(videos) < max_count:
        params = {
            "sec_uid": sec_uid,
            "count": min(20, max_count - len(videos)),
            "cursor": cursor
        }
        
        response = requests.get(base_url, params=params)
        data = json.loads(response.text)
        
        if data.get("status_code") != 0:
            print(f"请求错误: {data}")
            break
            
        aweme_list = data.get("aweme_list", [])
        videos.extend(aweme_list)
        
        if data.get("has_more") != 1:
            break
            
        cursor = data.get("max_cursor", 0)
        
    return videos[:max_count]

# 使用示例
sec_uid = "MS4wLjABAAAADgOltsr_SYTX6VurKA1H3n61xlFvYD1y_FrrY1UhI-o"
videos = get_user_videos(sec_uid, max_count=30)
print(f"获取到 {len(videos)} 个视频作品")

# 下载第一个视频
if videos:
    first_video = videos[0]
    video_url = first_video["video"]["play_addr"]["url_list"][0]
    response = requests.get(video_url, stream=True)
    
    with open(f"{first_video['aweme_id']}.mp4", "wb") as f:
        for chunk in response.iter_content(chunk_size=1024):
            if chunk:
                f.write(chunk)
                
    print(f"视频下载完成: {first_video['aweme_id']}.mp4")

JavaScript调用示例

/**
 * 获取用户视频作品列表
 * @param {string} sec_uid - 用户安全ID
 * @param {number} max_count - 最大获取数量
 * @returns {Promise<Array>} 视频列表
 */
async function getUserVideos(sec_uid, max_count = 50) {
    const videos = [];
    let cursor = 0;
    const base_url = "https://api.example.com/API/user_post_info_video.json";
    
    while (videos.length < max_count) {
        const count = Math.min(20, max_count - videos.length);
        const url = new URL(base_url);
        url.searchParams.set("sec_uid", sec_uid);
        url.searchParams.set("count", count);
        url.searchParams.set("cursor", cursor);
        
        try {
            const response = await fetch(url);
            const data = await response.json();
            
            if (data.status_code !== 0) {
                console.error("请求错误:", data);
                break;
            }
            
            const aweme_list = data.aweme_list || [];
            videos.push(...aweme_list);
            
            if (data.has_more !== 1) {
                break;
            }
            
            cursor = data.max_cursor || 0;
        } catch (error) {
            console.error("请求失败:", error);
            break;
        }
    }
    
    return videos.slice(0, max_count);
}

// 使用示例
const sec_uid = "MS4wLjABAAAADgOltsr_SYTX6VurKA1H3n61xlFvYD1y_FrrY1UhI-o";
getUserVideos(sec_uid, 30)
    .then(videos => {
        console.log(`获取到 ${videos.length} 个视频作品`);
        
        // 下载第一个视频
        if (videos.length > 0) {
            const firstVideo = videos[0];
            const videoUrl = firstVideo.video.play_addr.url_list[0];
            
            fetch(videoUrl)
                .then(response => response.blob())
                .then(blob => {
                    const url = URL.createObjectURL(blob);
                    const a = document.createElement('a');
                    a.href = url;
                    a.download = `${firstVideo.aweme_id}.mp4`;
                    document.body.appendChild(a);
                    a.click();
                    document.body.removeChild(a);
                    URL.revokeObjectURL(url);
                    console.log(`视频下载完成: ${firstVideo.aweme_id}.mp4`);
                });
        }
    });

Java调用示例

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;

public class TikTokApiClient {
    private static final String BASE_URL = "https://api.example.com/API/user_post_info_video.json";
    
    /**
     * 获取用户视频作品列表
     * @param secUid 用户安全ID
     * @param maxCount 最大获取数量
     * @return 视频列表
     */
    public List<JSONObject> getUserVideos(String secUid, int maxCount) {
        List<JSONObject> videos = new ArrayList<>();
        int cursor = 0;
        
        try (CloseableHttpClient httpclient = HttpClients.createDefault()) {
            while (videos.size() < maxCount) {
                int count = Math.min(20, maxCount - videos.size());
                
                URIBuilder builder = new URIBuilder(BASE_URL);
                builder.setParameter("sec_uid", secUid);
                builder.setParameter("count", String.valueOf(count));
                builder.setParameter("cursor", String.valueOf(cursor));
                URI uri = builder.build();
                
                HttpGet httpget = new HttpGet(uri);
                try (CloseableHttpResponse response = httpclient.execute(httpget)) {
                    HttpEntity entity = response.getEntity();
                    if (entity != null) {
                        String responseString = EntityUtils.toString(entity);
                        JSONObject data = JSON.parseObject(responseString);
                        
                        if (data.getInteger("status_code") != 0) {
                            System.err.println("请求错误: " + data);
                            break;
                        }
                        
                        JSONArray awemeList = data.getJSONArray("aweme_list");
                        if (awemeList != null) {
                            for (int i = 0; i < awemeList.size(); i++) {
                                videos.add(awemeList.getJSONObject(i));
                            }
                        }
                        
                        if (data.getInteger("has_more") != 1) {
                            break;
                        }
                        
                        cursor = data.getInteger("max_cursor");
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        
        return videos.subList(0, Math.min(videos.size(), maxCount));
    }
    
    /**
     * 下载视频
     * @param videoUrl 视频URL
     * @param fileName 保存文件名
     */
    public void downloadVideo(String videoUrl, String fileName) {
        try (CloseableHttpClient httpclient = HttpClients.createDefault()) {
            HttpGet httpget = new HttpGet(videoUrl);
            try (CloseableHttpResponse response = httpclient.execute(httpget)) {
                HttpEntity entity = response.getEntity();
                if (entity != null) {
                    try (InputStream in = entity.getContent();
                         FileOutputStream out = new FileOutputStream(fileName)) {
                        byte[] buffer = new byte[1024];
                        int len;
                        while ((len = in.read(buffer)) != -1) {
                            out.write(buffer, 0, len);
                        }
                        System.out.println("视频下载完成: " + fileName);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    public static void main(String[] args) {
        TikTokApiClient client = new TikTokApiClient();
        String secUid = "MS4wLjABAAAADgOltsr_SYTX6VurKA1H3n61xlFvYD1y_FrrY1UhI-o";
        
        List<JSONObject> videos = client.getUserVideos(secUid, 30);
        System.out.println("获取到 " + videos.size() + " 个视频作品");
        
        if (!videos.isEmpty()) {
            JSONObject firstVideo = videos.get(0);
            String videoUrl = firstVideo.getJSONObject("video")
                    .getJSONObject("play_addr")
                    .getJSONArray("url_list")
                    .getString(0);
            
            client.downloadVideo(videoUrl, firstVideo.getString("aweme_id") + ".mp4");
        }
    }
}

错误码及解决方案

错误码描述可能原因解决方案
0成功请求正常-
10001参数错误参数缺失或格式错误检查必填参数,确保格式正确
10002授权失败用户未授权或授权过期重新获取用户授权
10003访问频率限制API调用过于频繁降低调用频率,实现合理的重试机制
10004资源不存在请求的资源已被删除或不存在检查资源ID是否正确
10005服务器内部错误服务器处理异常稍后重试,如持续出现联系技术支持

错误处理最佳实践

def safe_api_request(url, params):
    """带错误处理的API请求"""
    max_retries = 3
    retry_delay = 2  # 秒
    
    for attempt in range(max_retries):
        try:
            response = requests.get(url, params=params, timeout=10)
            data = json.loads(response.text)
            
            if data.get("status_code") == 0:
                return data
            elif data.get("status_code") == 10003:
                print(f"访问频率限制,将在 {retry_delay} 秒后重试")
                time.sleep(retry_delay)
                retry_delay *= 2  # 指数退避
            else:
                print(f"API错误: {data.get('status_code')}, 消息: {data.get('message')}")
                return None
                
        except requests.exceptions.RequestException as e:
            print(f"请求异常: {e}")
            if attempt < max_retries - 1:
                print(f"将在 {retry_delay} 秒后重试")
                time.sleep(retry_delay)
                retry_delay *= 2
                
    print(f"达到最大重试次数 {max_retries}")
    return None

性能优化建议

1. 批量请求优化

  • 减少请求次数:合理设置count参数,最大可设为50,减少分页请求次数
  • 并发请求:使用多线程/多协程并发请求不同用户的数据,但需控制并发数
  • 请求合并:对于多个独立的资源请求,考虑合并为批量请求(如支持)

2. 缓存策略

mermaid

3. 下载优化

  • 断点续传:支持大文件断点续传,避免网络中断后重新下载
  • 分片下载:大文件采用分片下载,提高下载速度
  • CDN加速:使用CDN加速下载,选择距离用户最近的节点

安全注意事项

  1. 用户数据保护:获取的用户数据需严格保密,不得泄露或用于未授权用途
  2. API密钥管理:不要在客户端代码中硬编码API密钥,使用后端代理
  3. 请求签名:敏感操作需使用请求签名机制,防止请求被篡改
  4. 合规使用:遵守抖音API使用规范,合理使用API,避免滥用

总结与展望

TikTokDownload API接口提供了全面的抖音内容获取能力,通过本文的解析,开发者可以快速掌握各接口的使用方法和最佳实践。无论是构建内容分析工具、批量下载应用还是二次创作平台,这些API都能提供坚实的技术支持。

项目未来可能的发展方向:

  • 增加直播内容获取接口
  • 支持更多筛选条件的高级搜索
  • 提供AI内容分析功能
  • 增强数据导出和报告生成能力

建议开发者持续关注项目更新,及时了解新功能和接口变化。如有任何问题或需求,可以通过项目的Issue系统反馈。


如果你觉得本文对你有帮助,请点赞、收藏、关注三连,以便获取更多API使用技巧和最佳实践。下期预告:《TikTokDownload高级应用:从数据爬取到内容分析》

【免费下载链接】TikTokDownload 抖音去水印批量下载用户主页作品、喜欢、收藏、图文、音频 【免费下载链接】TikTokDownload 项目地址: https://gitcode.com/gh_mirrors/ti/TikTokDownload

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值