Перейти к содержимому
Socialift
Разделы документации
Справочник SDK

Справочник TikTok Python SDK

Клиент TikTok в Python SDK Socialift работает с TikTok Open API v2 (Login Kit, профиль, список видео, Content Posting API) и TikTok API for Business (метрики аккаунта, модерация комментариев). Все методы асинхронные и принимают токен пользователя аргументом, поэтому один клиент обслуживает многих авторов. Ниже — каждый метод по задачам, лимиты взяты из документации TikTok.

from socialift import TikTokМетодов: 26по версии socialift 1.3.0Обновлено:

Как создать клиент TikTok?

Создайте приложение на developers.tiktok.com и скопируйте его Client key и Client secret. Передайте их как client_key и client_secret или вызовите TikTok.from_env() — он читает переменные окружения TIKTOK_CLIENT_KEY и TIKTOK_CLIENT_SECRET. Лицензионный ключ Socialift берётся из SOCIALIFT_LICENSE_KEY (или аргумента license_key=).

Клиент не хранит токены: каждый метод принимает token аргументом. Access token действует 24 часа, refresh token — 365 дней, и при обновлении TikTok может вернуть новый refresh token — каждый раз перезаписывайте значение в базе.

По умолчанию login_url() запрашивает scope из DEFAULT_SCOPES (user.info.basic, user.info.profile, user.info.stats, video.list, video.upload, video.publish); если нужно меньше — передайте scopes=. Методам Business API (business_account, comments и др.) нужен ещё business_id — задайте его один раз через TikTok(..., business_id=open_id) или передавайте в каждый вызов.

Используйте клиент через async with — так HTTP-сессия корректно закрывается. Даже если TikTok возвращает ошибку внутри ответа HTTP 200, SDK превращает её в исключение вроде AuthError, PermissionError или RateLimitError.

python
import asyncio
import os
import secrets

from socialift import TikTok

# SOCIALIFT_LICENSE_KEY тоже должен быть задан
tt = TikTok(
    client_key=os.environ["TIKTOK_CLIENT_KEY"],
    client_secret=os.environ["TIKTOK_CLIENT_SECRET"],
)
# То же самое: tt = TikTok.from_env()


async def main():
    async with tt:
        state = secrets.token_urlsafe(16)  # сохраните и сверьте в callback
        url = tt.login_url(redirect_uri="https://example.com/tiktok/callback", state=state)
        print(url)
        # в callback: bundle = await tt.exchange_code(code, redirect_uri=...)
        # профиль: me = await tt.me(bundle.access_token)


asyncio.run(main())

Вход и токены

OAuth через Login Kit: URL авторизации, обмен code, обновление и отзыв токена.

exchange_codefrom_envlogin_urlrefresh_tokenrevoke

Обменивает code из callback Login Kit на TokenBundle с access и refresh токенами. Вызывается один раз в обработчике редиректа.

await tt.exchange_code(
    code: str,
    *,
    redirect_uri: str,
    code_verifier: Optional[str] = None,
) -> socialift.models.TokenBundle
  • Access token действует 24 часа, refresh token — 365 дней.
  • Передайте тот же redirect_uri, что и в login_url(); если поток начат с PKCE, добавьте code_verifier.
  • Запрос отправляется в form-urlencoded, как требует токен-эндпоинт TikTok; если в ответе нет access_token, выбрасывается ApiError.

from_env

classmethod

Создаёт клиент с ключами из переменных окружения TIKTOK_CLIENT_KEY и TIKTOK_CLIENT_SECRET. Дополнительные аргументы (scopes, business_id, timeout, license_key …) уходят в конструктор.

TikTok.from_env(**kwargs) -> TikTok
  • Отсутствующая переменная превращается в пустую строку и здесь не падает: ошибка ConfigurationError появится, например, при вызове login_url().

Формирует URL авторизации TikTok Login Kit, на который нужно перенаправить пользователя. Метод синхронный и не делает сетевых запросов.

tt.login_url(
    *,
    redirect_uri: str,
    state: Optional[str] = None,
    scopes: Optional[list[str]] = None,
    code_challenge: Optional[str] = None,
    code_challenge_method: Optional[str] = None,
    disable_auto_auth: bool = False,
) -> str
  • redirect_uri должен совпадать с одним из зарегистрированных в приложении: абсолютный https, статический (без query и фрагмента), до 512 символов; в одном приложении — до 10 адресов.
  • Без scopes= используются scope клиента (DEFAULT_SCOPES, если в конструктор не передали свои); TikTok ждёт их через запятую — SDK склеивает сам.
  • Для десктоп-приложений PKCE обязателен: TikTok ждёт code_challenge как SHA-256 от verifier в hex и code_challenge_method="S256". SDK их не добавляет — передайте оба, а затем code_verifier в exchange_code().
  • При пустом client_key выбрасывается ConfigurationError.
Пример — python
url = tt.login_url(redirect_uri="https://siz.uz/cb", state=state)

Получает новый access token по сохранённому refresh token. Запускайте по расписанию: access token живёт всего 24 часа.

await tt.refresh_token(refresh_token: str) -> socialift.models.TokenBundle
  • TikTok может вернуть refresh_token, отличный от отправленного, — всегда сохраняйте новое значение из полученного bundle.
  • Refresh token действует 365 дней.
Пример — python
bundle = await tt.refresh_token(refresh_token)

revoke

async

Отзывает access token, и приложение теряет доступ к аккаунту пользователя. Используйте, когда пользователь нажимает «отключить».

await tt.revoke(token: str) -> bool
  • Возвращает True, если TikTok принял запрос; удалите токены и в своей базе.
Пример — python
await tt.revoke(token)

Профиль и видео

Профиль автора и его собственные видео (Open API v2).

iter_videosmevideovideos

Проходит по страницам через videos() и собирает до max_items видео в один список. Удобно для синхронизации библиотеки автора с вашей базой.

await tt.iter_videos(
    token: str,
    *,
    max_items: int = 100,
    fields: Optional[str] = None,
) -> list[dict]
  • max_items (по умолчанию 100) — предохранитель: у крупных аккаунтов тысячи видео, и бесконечный цикл упрётся в rate limit.
  • Каждая страница — отдельный запрос максимум на 20 видео.

Нужные разрешения:video.list

Пример — python
page = await tt.videos(token, limit=20)
all_videos = await tt.iter_videos(token, max_items=100)

me

async

Возвращает профиль автора как Profile: id (open_id), имя, аватар, био, число подписчиков, подписок и видео. Удобно сразу после входа, чтобы показать, кто подключился.

await tt.me(token: str, *, fields: Optional[str] = None) -> socialift.models.Profile
  • Scope по полям: open_id, аватар и display_name — user.info.basic; bio_description, profile_deep_link, is_verified — user.info.profile; follower_count, following_count, likes_count, video_count — user.info.stats.
  • По умолчанию запрашиваются все эти поля; чтобы получить только поля выданных scope, передайте в fields более короткую строку.
  • И Profile.username, и full_name содержат display_name; исходный объект TikTok лежит в raw.

Нужные разрешения:user.info.basicuser.info.profileuser.info.stats

Пример — python
me = await tt.me(token)

video

async

Получает данные видео по конкретным ID — например, чтобы обновить счётчики или истекающие ссылки на обложки уже известных видео.

await tt.video(
    video_ids: Iterable[str],
    token: str,
    *,
    fields: Optional[str] = None,
) -> list[dict]
  • TikTok принимает до 20 ID за запрос; SDK молча берёт только первые 20.
  • Не рассчитывайте, что порядок результатов совпадёт с порядком ID, — сопоставляйте по id.
  • Нужен scope video.list.

Нужные разрешения:video.list

Пример — python
videos = await tt.video(["7300000000000000000"], token)

videos

async

Возвращает одну страницу собственных видео автора в виде {"data", "cursor", "has_more"}. Подходит для постраничного списка в интерфейсе.

await tt.videos(
    token: str,
    *,
    limit: int = 20,
    cursor: Optional[int] = None,
    fields: Optional[str] = None,
) -> dict
  • TikTok отдаёт максимум 20 видео за запрос; limit приводится к диапазону 1–20.
  • cursor — UTC Unix-время в миллисекундах: для более старых видео передайте cursor из предыдущей страницы.
  • Нужен scope video.list.

Нужные разрешения:video.list

Пример — python
page = await tt.videos(token, limit=20)
all_videos = await tt.iter_videos(token, max_items=100)

Публикация

Content Posting API: прямая публикация, черновик во входящих, фото-пост и отслеживание статуса.

creator_infopublish_photospublish_statuspublish_videoupload_videowait_publish

Возвращает текущие настройки публикации автора: допустимые privacy_level_options, max_video_post_duration_sec, отключены ли комментарии, дуэты и stitch. Вызывайте перед каждым постом и стройте форму публикации по этому ответу.

await tt.creator_info(token: str) -> dict
  • Поток Direct Post в TikTok предполагает запрос creator info до инициализации поста.
  • Отправляемый privacy_level должен быть одним из privacy_level_options.
  • Поля с дневной квотой в ответе нет; когда автор упирается в дневной лимит постов через API, TikTok возвращает spam_risk_too_many_posts, а SDK выбрасывает RateLimitError.
  • Нужен scope video.publish.

Нужные разрешения:video.publish

Пример — python
info = await tt.creator_info(token)
print(info["privacy_level_options"])

Создаёт фото-пост (карусель) из ссылок на изображения — публикует сразу или с draft=True отправляет черновиком во входящие автора.

await tt.publish_photos(
    token: str,
    *,
    photo_urls: list[str],
    title: Optional[str] = None,
    description: Optional[str] = None,
    privacy_level: str = 'SELF_ONLY',
    cover_index: int = 0,
    disable_comment: bool = False,
    auto_add_music: bool = True,
    draft: bool = False,
    wait: bool = False,
    brand_content: bool = False,
    brand_organic: bool = False,
) -> dict
  • До 35 изображений, JPEG или WebP, до 20 МБ каждое; принимаются только ссылки (PULL_FROM_URL) с подтверждённого домена.
  • title — до 90, description — до 4000 символов UTF-16; cover_index считается с нуля.
  • Для прямой публикации нужен scope video.publish, для draft=True (MEDIA_UPLOAD) — video.upload. auto_add_music работает только при прямой публикации.
  • Не используйте wait=True вместе с draft=True: статус остаётся SEND_TO_USER_INBOX, пока автор не опубликует пост.

Нужные разрешения:video.publish

Пример — python
result = await tt.publish_photos(token, photo_urls=["https://cdn.siz.uz/1.jpg"], title="Karusel")

Возвращает текущее состояние обработки поста по publish_id. Опрашивайте сами или используйте wait_publish().

await tt.publish_status(publish_id: str, token: str) -> dict
  • Значения status: PROCESSING_UPLOAD (загрузка файла), PROCESSING_DOWNLOAD (скачивание по URL), SEND_TO_USER_INBOX (черновики), PUBLISH_COMPLETE, FAILED (причина в fail_reason).
  • Лимит — 30 запросов в минуту на access token.
  • publicaly_available_post_id (так пишет TikTok) приходит, только когда пост публичный и прошёл модерацию.
Пример — python
status = await tt.publish_status(publish_id, token)

Публикует видео сразу в профиль автора (Direct Post) по публичной ссылке или из байтов/пути к файлу. Возвращает {"publish_id"}, а при wait=True — ещё и итоговый status.

await tt.publish_video(
    token: str,
    *,
    video_url: Optional[str] = None,
    video: Union[bytes, str, os.PathLike, NoneType] = None,
    title: Optional[str] = None,
    privacy_level: str = 'SELF_ONLY',
    disable_comment: bool = False,
    disable_duet: bool = False,
    disable_stitch: bool = False,
    cover_timestamp_ms: Optional[int] = None,
    brand_content: bool = False,
    brand_organic: bool = False,
    chunk_size: Optional[int] = None,
    wait: bool = False,
) -> dict
  • Пока приложение не прошло аудит TikTok, всё, что оно публикует, ограничено приватным просмотром, — поэтому privacy_level по умолчанию SELF_ONLY.
  • Для video_url (PULL_FROM_URL) домен или префикс URL должен быть подтверждён, адрес — https без редиректов, иначе url_ownership_unverified (PermissionError). TikTok прекращает скачивание через час.
  • С video= SDK загружает файл частями: до 5 МБ — одним куском, больше — частями по 5–64 МБ (chunk_size).
  • Запросы инициализации ограничены 6 в минуту на access token. Нужен scope video.publish.

Нужные разрешения:video.publishvideo.upload

Пример — python
result = await tt.publish_video(token, video_url="https://cdn.siz.uz/reel.mp4", title="Salom TikTok!",
                              privacy_level="SELF_ONLY", wait=True)
Пример — python
with open("reel.mp4", "rb") as f:
    result = await tt.publish_video(token, video=f.read(), title="Salom!")

Отправляет видео черновиком во входящие автора в TikTok, не публикуя его; автор редактирует и публикует сам в приложении. Используйте, когда подпись и приватность должен выбрать автор.

await tt.upload_video(
    token: str,
    *,
    video_url: Optional[str] = None,
    video: Union[bytes, str, os.PathLike, NoneType] = None,
    chunk_size: Optional[int] = None,
    wait: bool = False,
) -> dict
  • Нужен scope video.upload; параметров подписи и приватности здесь нет.
  • TikTok допускает не больше 5 ожидающих отправок за любые 24 часа.
  • Статус останавливается на SEND_TO_USER_INBOX и становится PUBLISH_COMPLETE только после публикации автором. wait=True ждёт именно PUBLISH_COMPLETE, поэтому завершится ApiError, если автор не опубликует видео примерно за 2 минуты.
  • Правила источника те же, что у publish_video(): для video_url нужен подтверждённый домен, video= загружается частями.

Опрашивает publish_status(), пока пост не достигнет PUBLISH_COMPLETE, и возвращает этот статус. Именно его использует publish_video(wait=True).

await tt.wait_publish(
    publish_id: str,
    token: str,
    *,
    attempts: int = 40,
    delay: float = 3.0,
) -> dict
  • По умолчанию 40 попыток × 3 секунды, около 2 минут; меняется через attempts и delay.
  • При FAILED выбрасывается ApiError с fail_reason; когда попытки заканчиваются — тоже ApiError.
  • SEND_TO_USER_INBOX не считается завершением — не используйте метод для черновиков во входящих.

Бизнес-аккаунт и комментарии

TikTok API for Business: метрики аккаунта и модерация комментариев. Нужен business_id.

business_accountbusiness_videoscommentsdelete_commenthide_commentlike_commentpin_commentreply_comment

Возвращает профиль бизнес-аккаунта и метрики по дням через TikTok API for Business. Для аналитики на уровне аккаунта.

await tt.business_account(
    token: str,
    *,
    business_id: Optional[str] = None,
    fields: Optional[list[str]] = None,
) -> dict
  • Запрос идёт на business-api.tiktok.com с заголовком Access-Token — это отдельное семейство API, не Open API, который использует me(); приложению нужен доступ к TikTok API for Business.
  • Нужен business_id (обычно open_id автора): передайте аргументом или задайте business_id= в клиенте, иначе ConfigurationError.
  • fields — список Python; SDK отправляет его строкой с JSON-массивом.
Пример — python
account = await tt.business_account(token)

Возвращает видео бизнес-аккаунта с метриками по каждому через TikTok API for Business, постранично.

await tt.business_videos(
    token: str,
    *,
    business_id: Optional[str] = None,
    cursor: Optional[int] = None,
    max_count: int = 20,
    fields: Optional[list[str]] = None,
) -> dict
  • Для следующей страницы передайте cursor из предыдущего ответа; max_count по умолчанию 20.
  • Нужны business_id (аргумент или значение клиента) и доступ к TikTok API for Business.
Пример — python
stats = await tt.business_videos(token, max_count=20)

Возвращает комментарии к одному видео бизнес-аккаунта; include_replies=True добавляет ответы на комментарии первого уровня.

await tt.comments(
    video_id: str,
    token: str,
    *,
    business_id: Optional[str] = None,
    cursor: Optional[int] = None,
    max_count: int = 30,
    include_replies: bool = False,
) -> dict
  • Возвращается объект data из ответа; следующая страница — через cursor, max_count по умолчанию 30.
  • Нужны business_id и доступ к TikTok API for Business.
Пример — python
comments = await tt.comments("7300000000000000000", token, max_count=30)

Удаляет комментарий через TikTok API for Business. Чтобы убрать комментарий из вида, не удаляя его, используйте hide_comment().

await tt.delete_comment(
    comment_id: str,
    token: str,
    *,
    business_id: Optional[str] = None,
) -> dict
  • Нужны business_id и доступ к TikTok API for Business.
Пример — python
await tt.delete_comment(comment_id, token)

Скрывает комментарий под видео бизнес-аккаунта или снова показывает его при hidden=False — обратимый способ модерации.

await tt.hide_comment(
    comment_id: str,
    token: str,
    *,
    hidden: bool = True,
    business_id: Optional[str] = None,
) -> dict
  • В action отправляется HIDE или UNHIDE; нужен business_id.
Пример — python
await tt.hide_comment(comment_id, token, hidden=True)

Ставит лайк комментарию от имени бизнес-аккаунта или снимает его при liked=False.

await tt.like_comment(
    comment_id: str,
    token: str,
    *,
    liked: bool = True,
    business_id: Optional[str] = None,
) -> dict
  • В action отправляется LIKE или UNLIKE; нужен business_id.
Пример — python
await tt.like_comment(comment_id, token, liked=True)

Закрепляет комментарий вверху видео или открепляет его при pinned=False.

await tt.pin_comment(
    comment_id: str,
    token: str,
    *,
    pinned: bool = True,
    business_id: Optional[str] = None,
) -> dict
  • Отправляет в business/comment/top/ action TOP или UNTOP; нужен business_id.
Пример — python
await tt.pin_comment(comment_id, token, pinned=True)

Публикует ответ от имени бизнес-аккаунта на комментарий к его видео.

await tt.reply_comment(
    comment_id: str,
    token: str,
    text: str,
    *,
    video_id: Optional[str] = None,
    business_id: Optional[str] = None,
) -> dict
  • Порядок аргументов: comment_id, token, text; video_id в SDK необязателен, но передавайте его, если он известен.
  • Нужны business_id и доступ к TikTok API for Business.
Пример — python
await tt.reply_comment(comment_id, token, "Rahmat!", video_id=video_id)

Низкоуровневые вызовы

Прямой доступ к эндпоинтам, для которых в SDK нет обёртки.

businesscallrequest

Вызывает любой эндпоинт TikTok API for Business с заголовком Access-Token. Для возможностей Business API, которые SDK не оборачивает.

await tt.business(
    path: str,
    token: str,
    *,
    method: str = 'POST',
    json: Optional[dict] = None,
    params: Optional[dict] = None,
) -> dict
  • path указывается относительно https://business-api.tiktok.com/open_api/v1.3/; завершающий / добавляется автоматически.
  • Метод по умолчанию — POST; ненулевой code в теле ответа превращается в исключение.
  • business_id сам не добавляется — положите его в params или json.
Пример — python
data = await tt.business("business/get/", token, method="GET", params={"business_id": open_id})

call

async

Вызывает любой эндпоинт Open API v2, для которого в SDK ещё нет обёртки, с заголовком Authorization: Bearer и проверкой ошибок TikTok. Возвращает сырой JSON.

await tt.call(
    path: str,
    token: str,
    *,
    method: str = 'POST',
    json: Optional[dict] = None,
    params: Optional[dict] = None,
) -> dict
  • path указывается относительно https://open.tiktokapis.com/v2/; обязательный для TikTok завершающий / добавляется автоматически.
  • Метод по умолчанию — POST; query-параметры вроде fields передаются в params, тело запроса — в json.
  • Порядок аргументов — path, token (в Ads.call токен идёт первым).

request

async

Самый низкоуровневый HTTP-вызов: отправляет запрос на полный URL с повторами и выбрасывает ошибку, даже если TikTok вернул её внутри HTTP 200. Обычно удобнее call() или business(), которые сами добавляют заголовок авторизации.

await tt.request(method: str, url: str, **kwargs) -> Any
  • Заголовок авторизации не добавляется — передайте headers сами.
  • Если error.code не "ok" (Open API) или code не ноль (Business API), выбрасывается наследник ApiError.
  • Повторы — по RetryPolicy (ответы 429 и 5xx).

Общие методы всех клиентов

У каждого HTTP-клиента (Telegram, Facebook, Instagram, LinkedIn, TikTok, Ads) есть эти низкоуровневые методы: чтобы вызвать эндпоинт, для которого в SDK ещё нет обёртки, или читать данные постранично. По завершении блока async with соединение закрывается автоматически.

request

async

Отправляет произвольный HTTP-запрос и возвращает JSON-ответ — для эндпоинта, у которого в SDK пока нет отдельного метода. Токен и параметры подписи (access_token, для Meta — appsecret_proof через socialift.crypto.appsecret_proof) вы передаёте сами в params или headers.

await tt.request(
    method: str,
    url: str,
    *,
    params: Optional[Mapping[str, Any]] = None,
    data: Optional[Any] = None,
    json: Optional[Any] = None,
    headers: Optional[Mapping[str, str]] = None,
) -> Any
  • Значения None в params не отправляются.
  • При лимите (RateLimitError) и временных ошибках сервера (HTTP 429, 500, 502, 503, 504) запрос повторяется по RetryPolicy; если есть заголовок Retry-After, SDK ждёт указанное время. Обрыв сети выбрасывается как TransportError.

get

async

Короткая форма request("GET", ...).

await tt.get(url: str, **kw) -> Any

post

async

Короткая форма request("POST", ...).

await tt.post(url: str, **kw) -> Any

delete

async

Короткая форма request("DELETE", ...).

await tt.delete(url: str, **kw) -> Any

Проходит по курсорной пагинации Meta (paging.next) и возвращает все элементы data одним списком.

await tt.paginate(
    url: str,
    *,
    params: Optional[Mapping[str, Any]] = None,
    max_items: int = 500,
    page_size: int = 100,
) -> list[dict]
  • max_items (по умолчанию 500) — защитный предел: у крупного аккаунта могут быть десятки тысяч записей. page_size — limit одного запроса.

close

async

Закрывает HTTP-сессию, созданную самим SDK (переданную извне сессию не трогает). При использовании async with Client(...) вызывается автоматически.

await tt.close() -> None

Частые вопросы

Сколько живёт access token TikTok?

Access token действует 24 часа, refresh token — 365 дней. Обновляйте токен через refresh_token() минимум раз в сутки. TikTok может вернуть при обновлении другой refresh token — сохраняйте полученное значение и в следующий раз используйте именно его.

Почему видео, опубликованное в TikTok через API, видно только мне?

Весь контент, который публикует приложение без пройденного аудита TikTok, ограничивается приватным режимом просмотра. Поэтому в SDK privacy_level по умолчанию равен SELF_ONLY. После аудита выбирайте значение из списка privacy_level_options, который возвращает creator_info().

Можно ли загрузить видео в TikTok из файла, а не по URL?

Да: передайте байты или путь к файлу в publish_video(token, video=...). SDK использует FILE_UPLOAD и режет файлы больше 5 МБ на части по 5–64 МБ. Для video_url (PULL_FROM_URL) домен или префикс URL должен быть подтверждён в TikTok, адрес — https и без редиректов.

Чем publish_video отличается от upload_video?

publish_video публикует видео сразу в профиль (Direct Post, scope video.publish). upload_video отправляет видео черновиком во входящие автора в TikTok (scope video.upload): автор редактирует и публикует его сам в приложении. TikTok допускает не больше 5 ожидающих отправок за любые 24 часа.

Можно ли читать комментарии TikTok и отвечать на них через API?

Да, в SDK для этого есть comments, reply_comment, hide_comment и другие методы. Они работают через TikTok API for Business (business-api.tiktok.com) с заголовком Access-Token. Нужны business_id (обычно open_id автора) и доступ вашего приложения к этому API.

Источники

  1. TikTok for Developers — Manage User Access Tokens
  2. TikTok for Developers — Content Posting API: Direct Post
  3. TikTok for Developers — Content Posting API: Upload
  4. TikTok for Developers — Content Posting API: Photo Post
  5. TikTok for Developers — Media Transfer Guide
  6. TikTok for Developers — Get Post Status

Связанные страницы