├── .gitignore
├── src
├── Response
│ ├── Model
│ │ ├── Artist.php
│ │ ├── ExternalSongInfo.php
│ │ ├── ExtraAttr.php
│ │ ├── ReviewResult.php
│ │ ├── ChallengeList.php
│ │ ├── Data.php
│ │ ├── Position.php
│ │ ├── GroupIdList.php
│ │ ├── Room.php
│ │ ├── SearchHighlight.php
│ │ ├── Action.php
│ │ ├── LimitsInfo.php
│ │ ├── Icon.php
│ │ ├── Media.php
│ │ ├── LabelTop.php
│ │ ├── CommerceInfo.php
│ │ ├── Thumbnail.php
│ │ ├── MatchedPgcSound.php
│ │ ├── RiskInfos.php
│ │ ├── Download.php
│ │ ├── DownloadGeneral.php
│ │ ├── DownloadMaskPanel.php
│ │ ├── ShareGeneral.php
│ │ ├── Extra.php
│ │ ├── TextExtra.php
│ │ ├── MatchedSong.php
│ │ ├── BitRate.php
│ │ ├── AwemeAcl.php
│ │ ├── Play.php
│ │ ├── UserSearchItem.php
│ │ ├── Anchor.php
│ │ ├── StickerDetail.php
│ │ ├── Statistics.php
│ │ ├── Status.php
│ │ ├── VideoControl.php
│ │ ├── ShareInfo.php
│ │ ├── Comment.php
│ │ ├── TikTok.php
│ │ ├── MusicSearchItem.php
│ │ ├── ChaListItem.php
│ │ ├── ChallengeInfo.php
│ │ ├── Video.php
│ │ ├── Author.php
│ │ ├── Lives.php
│ │ ├── Music.php
│ │ └── AwemeDetail.php
│ └── APIResponse.php
├── Exception
│ ├── NetworkException.php
│ ├── ForbiddenException.php
│ ├── NotFoundException.php
│ ├── BadRequestException.php
│ ├── ProxyAuthException.php
│ ├── TooManyRequestsException.php
│ └── TikTokException.php
├── AutoPropertyMapper.php
├── Response.php
├── Request.php
└── TikTok.php
├── LICENSE
├── composer.json
├── examples
├── getUnshortenedUrl.php
├── getNoWatermarkUrl.php
├── getNoWatermarkUrlByID.php
├── getVideoByID.php
├── getVideoByUrl.php
├── searchMusic.php
├── searchVideo.php
├── searchHashtag.php
├── searchUser.php
├── searchLive.php
├── getCommentsByID.php
└── getCommentsByUrl.php
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | .vscode
--------------------------------------------------------------------------------
/src/Response/Model/Artist.php:
--------------------------------------------------------------------------------
1 | 'bool'
19 | ];
20 | }
21 |
--------------------------------------------------------------------------------
/src/Response/Model/ReviewResult.php:
--------------------------------------------------------------------------------
1 | 'int'
19 | ];
20 | }
21 |
--------------------------------------------------------------------------------
/src/AutoPropertyMapper.php:
--------------------------------------------------------------------------------
1 | 'ChallengeInfo',
19 | ];
20 | }
21 |
--------------------------------------------------------------------------------
/src/Response/Model/Data.php:
--------------------------------------------------------------------------------
1 | 'int',
23 | 'lives' => 'Lives'
24 | ];
25 | }
26 |
--------------------------------------------------------------------------------
/src/Response/Model/Position.php:
--------------------------------------------------------------------------------
1 | 'int',
23 | 'end' => 'int'
24 | ];
25 | }
26 |
--------------------------------------------------------------------------------
/src/Response/Model/GroupIdList.php:
--------------------------------------------------------------------------------
1 | '',
23 | 'GroupdIdList1' => ''
24 | ];
25 | }
26 |
--------------------------------------------------------------------------------
/src/Response/Model/Room.php:
--------------------------------------------------------------------------------
1 | 'bool',
24 | 'is_battle' => 'bool'
25 | ];
26 | }
27 |
--------------------------------------------------------------------------------
/src/Response/Model/SearchHighlight.php:
--------------------------------------------------------------------------------
1 | 'string',
23 | 'positions' => 'Position[]'
24 | ];
25 | }
26 |
--------------------------------------------------------------------------------
/src/Response/Model/Action.php:
--------------------------------------------------------------------------------
1 | 'Icon',
28 | 'schema' => 'string',
29 | 'action_type' => 'int'
30 | ];
31 | }
32 |
--------------------------------------------------------------------------------
/src/Response/Model/LimitsInfo.php:
--------------------------------------------------------------------------------
1 | 'string',
27 | 'requests_count' => 'int',
28 | 'requests_limit' => 'int',
29 | ];
30 | }
31 |
--------------------------------------------------------------------------------
/src/Response/Model/Icon.php:
--------------------------------------------------------------------------------
1 | 'string',
31 | 'url_list' => 'string[]',
32 | 'width' => 'int',
33 | 'height' => 'int'
34 | ];
35 | }
36 |
--------------------------------------------------------------------------------
/src/Response/Model/Media.php:
--------------------------------------------------------------------------------
1 | 'string',
31 | 'url_list' => 'string[]',
32 | 'width' => 'int',
33 | 'height' => 'int'
34 | ];
35 | }
36 |
--------------------------------------------------------------------------------
/src/Response/Model/LabelTop.php:
--------------------------------------------------------------------------------
1 | 'string',
31 | 'url_list' => 'string[]',
32 | 'width' => 'int',
33 | 'height' => 'int'
34 | ];
35 | }
36 |
--------------------------------------------------------------------------------
/src/Response/Model/CommerceInfo.php:
--------------------------------------------------------------------------------
1 | 'bool',
27 | 'with_comment_filter_words' => 'bool',
28 | 'adv_promotable' => 'bool'
29 | ];
30 | }
31 |
--------------------------------------------------------------------------------
/src/Response/Model/Thumbnail.php:
--------------------------------------------------------------------------------
1 | 'int',
31 | 'uri' => 'string',
32 | 'url_list' => 'string[]',
33 | 'width' => 'int'
34 | ];
35 | }
36 |
--------------------------------------------------------------------------------
/src/Response/Model/MatchedPgcSound.php:
--------------------------------------------------------------------------------
1 | 'string',
31 | 'mixed_author' => 'string',
32 | 'author' => 'string',
33 | 'title' => 'string'
34 | ];
35 | }
36 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022-2024 Evelode
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/src/Response/Model/RiskInfos.php:
--------------------------------------------------------------------------------
1 | 'bool',
35 | 'war' => 'bool',
36 | 'risk_sink' => 'bool',
37 | 'type' => 'int',
38 | 'content' => 'string'
39 | ];
40 | }
41 |
--------------------------------------------------------------------------------
/src/Response/Model/Download.php:
--------------------------------------------------------------------------------
1 | 'string',
35 | 'url_list' => 'string[]',
36 | 'width' => 'int',
37 | 'height' => 'int',
38 | 'data_size' => 'int',
39 | ];
40 | }
41 |
--------------------------------------------------------------------------------
/src/Response/Model/DownloadGeneral.php:
--------------------------------------------------------------------------------
1 | 'int',
35 | 'show_type' => 'int',
36 | 'transcode' => 'int',
37 | 'mute' => 'bool',
38 | 'extra' => 'string'
39 | ];
40 | }
41 |
--------------------------------------------------------------------------------
/src/Response/Model/DownloadMaskPanel.php:
--------------------------------------------------------------------------------
1 | 'int',
35 | 'show_type' => 'int',
36 | 'transcode' => 'int',
37 | 'mute' => 'bool',
38 | 'extra' => 'string'
39 | ];
40 | }
41 |
--------------------------------------------------------------------------------
/src/Response/Model/ShareGeneral.php:
--------------------------------------------------------------------------------
1 | 'int',
39 | 'show_type' => 'int',
40 | 'transcode' => 'int',
41 | 'mute' => 'bool',
42 | 'extra' => 'string',
43 | 'toast_msg' => 'string'
44 | ];
45 | }
46 |
--------------------------------------------------------------------------------
/src/Exception/TikTokException.php:
--------------------------------------------------------------------------------
1 | _response !== null ? true : false;
29 | }
30 |
31 | /**
32 | * Get the full server response.
33 | *
34 | * @return Response|null The full response if one exists, otherwise NULL.
35 | *
36 | * @see TikTokException::hasResponse()
37 | */
38 | public function getResponse()
39 | {
40 | return $this->_response;
41 | }
42 |
43 | /**
44 | * Internal. Sets the value of the full server response.
45 | *
46 | * @param Response|null $response The response value.
47 | */
48 | public function setResponse(
49 | Response $response = null)
50 | {
51 | $this->_response = $response;
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/src/Response/Model/Extra.php:
--------------------------------------------------------------------------------
1 | 'int',
39 | 'hashtag_id' => 'string',
40 | 'hashtag_name' => 'string',
41 | 'is_commerce' => 'bool',
42 | 'start' => 'int',
43 | 'type' => 'int'
44 | ];
45 | }
46 |
--------------------------------------------------------------------------------
/src/Response/Model/TextExtra.php:
--------------------------------------------------------------------------------
1 | 'int',
39 | 'hashtag_id' => 'string',
40 | 'hashtag_name' => 'string',
41 | 'is_commerce' => 'bool',
42 | 'start' => 'int',
43 | 'type' => 'int'
44 | ];
45 | }
46 |
--------------------------------------------------------------------------------
/src/Response/Model/MatchedSong.php:
--------------------------------------------------------------------------------
1 | 'string',
39 | 'author' => 'string',
40 | 'title' => 'string',
41 | 'h5_url' => 'string',
42 | 'cover_medium' => 'Media',
43 | 'performers' => ''
44 | ];
45 | }
46 |
--------------------------------------------------------------------------------
/src/Response/Model/BitRate.php:
--------------------------------------------------------------------------------
1 | 'string',
39 | 'quality_type' => 'int',
40 | 'bit_rate' => 'int',
41 | 'play_addr' => 'Play',
42 | 'is_bytevc1' => 'int',
43 | 'dub_infos' => ''
44 | ];
45 | }
46 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "evelode/tiktok-api-php",
3 | "description": "TikTok REST API wrapper for PHP",
4 | "homepage": "https://github.com/evelode/tiktok-api-php",
5 | "type": "library",
6 | "require": {
7 | "php": ">=7.0",
8 | "sergeykomlev/lazyjsonmapper": "^2.0.0",
9 | "guzzlehttp/guzzle": "^7.4",
10 | "ext-curl": "*",
11 | "ext-mbstring": "*",
12 | "ext-gd": "*",
13 | "ext-exif": "*",
14 | "ext-zlib": "*",
15 | "ext-bcmath": "*"
16 | },
17 | "license": "MIT",
18 | "authors": [
19 | {
20 | "name": "Evelode",
21 | "email": "contact@evelode.com",
22 | "homepage": "https://evelode.com",
23 | "role": "Developer"
24 | }
25 | ],
26 | "suggest": {
27 | "ext-curl": "Required for CURL handler support in requests"
28 | },
29 | "autoload": {
30 | "psr-4": {
31 | "TikTokRESTAPI\\": "src/"
32 | }
33 | },
34 | "keywords": [
35 | "php",
36 | "php7",
37 | "rest-api",
38 | "php-library",
39 | "php-fpm",
40 | "scrapper",
41 | "php8",
42 | "tiktok",
43 | "tiktok-scraper",
44 | "tiktok-api",
45 | "tiktokapi",
46 | "tiktok-automation",
47 | "tiktok-downloader",
48 | "tiktok-signature",
49 | "ttencrypt",
50 | "nowatermark",
51 | "xgorgon",
52 | "xkhonos",
53 | "xtyhon",
54 | "xladon"
55 | ]
56 | }
57 |
--------------------------------------------------------------------------------
/src/Response/Model/AwemeAcl.php:
--------------------------------------------------------------------------------
1 | 'DownloadGeneral',
35 | 'download_mask_panel' => 'DownloadMaskPanel',
36 | 'share_list_status' => 'int',
37 | 'share_general' => 'ShareGeneral',
38 | 'platform_list' => ''
39 | ];
40 | }
41 |
--------------------------------------------------------------------------------
/src/Response/Model/Play.php:
--------------------------------------------------------------------------------
1 | 'string',
47 | 'url_list' => 'string[]',
48 | 'width' => 'int',
49 | 'height' => 'int',
50 | 'url_key' => 'string',
51 | 'data_size' => 'int',
52 | 'file_hash' => 'string',
53 | 'file_cs' => 'string'
54 | ];
55 | }
56 |
--------------------------------------------------------------------------------
/src/Response/APIResponse.php:
--------------------------------------------------------------------------------
1 | 'string',
39 | 'message' => 'string',
40 | 'limits_info' => 'Model\LimitsInfo',
41 | 'rate_limit_reached' => 'bool',
42 | 'tiktok' => 'Model\TikTok',
43 | 'timestamp' => 'string'
44 | ];
45 | }
46 |
--------------------------------------------------------------------------------
/src/Response/Model/UserSearchItem.php:
--------------------------------------------------------------------------------
1 | '',
47 | 'effects' => '',
48 | 'items' => '',
49 | 'mix_list' => '',
50 | 'musics' => '',
51 | 'position' => '',
52 | 'uniqid_position' => '',
53 | 'user_info' => 'User'
54 | ];
55 | }
56 |
--------------------------------------------------------------------------------
/src/Response/Model/Anchor.php:
--------------------------------------------------------------------------------
1 | 'string',
47 | 'thumbnail' => 'Thumbnail',
48 | 'actions' => 'Action[]',
49 | 'keyword' => 'string',
50 | 'id' => 'string',
51 | 'type' => 'int',
52 | 'icon' => 'Icon',
53 | 'log_extra' => ''
54 | ];
55 | }
56 |
--------------------------------------------------------------------------------
/src/Response/Model/StickerDetail.php:
--------------------------------------------------------------------------------
1 | 'string',
43 | 'name' => 'string',
44 | 'children' => '',
45 | 'owner_id' => 'string',
46 | 'tags' => 'string',
47 | 'sec_uid' => 'string',
48 | 'linked_anchors' => ''
49 | ];
50 | }
51 |
--------------------------------------------------------------------------------
/src/Response.php:
--------------------------------------------------------------------------------
1 | 'string',
28 | ];
29 |
30 | /** @var HttpResponseInterface */
31 | public $httpResponse;
32 |
33 | /**
34 | * Checks if the response was successful.
35 | *
36 | * @return bool
37 | */
38 | public function isOk()
39 | {
40 | return $this->_getProperty('status') === self::STATUS_OK;
41 | }
42 |
43 | /**
44 | * Gets the message.
45 | *
46 | * This function overrides the normal getter with some special processing
47 | * to handle unusual multi-error message values in certain responses.
48 | *
49 | * @throws RuntimeException If the message object is of an unsupported type.
50 | *
51 | * @return string|null A message string if one exists, otherwise NULL.
52 | */
53 | public function getMessage()
54 | {
55 | // Example:
56 | // {"message":"NO_POSITION","data":{}}
57 |
58 | $message = $this->_getProperty('message');
59 | if ($message === null || is_string($message)) {
60 | // Single error string or nothing at all.
61 | return $message;
62 | } else {
63 | throw new RuntimeException('Unknown message type in response.');
64 | }
65 | }
66 |
67 | /**
68 | * Gets the HTTP response.
69 | *
70 | * @return HttpResponseInterface
71 | */
72 | public function getHttpResponse()
73 | {
74 | return $this->httpResponse;
75 | }
76 |
77 | /**
78 | * Sets the HTTP response.
79 | *
80 | * @param HttpResponseInterface $response
81 | */
82 | public function setHttpResponse(
83 | HttpResponseInterface $response)
84 | {
85 | $this->httpResponse = $response;
86 | }
87 |
88 | /**
89 | * Checks if an HTTP response value exists.
90 | *
91 | * @return bool
92 | */
93 | public function isHttpResponse()
94 | {
95 | return $this->httpResponse !== null;
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/src/Response/Model/Statistics.php:
--------------------------------------------------------------------------------
1 | 'int',
59 | 'lose_comment_count' => 'int',
60 | 'aweme_id' => 'string',
61 | 'comment_count' => 'int',
62 | 'play_count' => 'int',
63 | 'share_count' => 'int',
64 | 'forward_count' => 'int',
65 | 'whatsapp_share_count' => 'int',
66 | 'digg_count' => 'int',
67 | 'download_count' => 'int',
68 | 'collect_count' => 'int'
69 | ];
70 | }
71 |
--------------------------------------------------------------------------------
/examples/getUnshortenedUrl.php:
--------------------------------------------------------------------------------
1 | setCacheTimeout(3600);
18 |
19 | try {
20 | // Validate the TikTok video URL
21 | // This is an example how to get $video_url from Console/Terminal
22 | if (empty($video_url)) {
23 | echo 'Enter the short TikTok video URL:';
24 | $video_url = trim(fgets(STDIN));
25 | }
26 |
27 | $resp = $tiktok->getUnshortenedUrl($video_url);
28 | if ($resp->isOk() && $resp->isTiktok() && $resp->getTiktok()->isUrl()) {
29 | echo sprintf('Full TikTok video URL: %s.', $resp->getTiktok()->getUrl());
30 | }
31 | } catch (TikTokRESTAPI\Exception\BadRequestException $e) {
32 | // Request not performed because some data is missing or incorrect.
33 | echo sprintf('BadRequestException Catched: %s', $e->getMessage()) . "\n";
34 | } catch (TikTokRESTAPI\Exception\ForbiddenException $e) {
35 | // Request failed due to invalid, expired, revoked license or access to API is restricted.
36 | echo sprintf('ForbiddenException Catched: %s', $e->getMessage()) . "\n";
37 | } catch (TikTokRESTAPI\Exception\NotFoundException $e) {
38 | // Requested resource doesn't exist in TikTok.
39 | echo sprintf('NotFoundException Catched: %s', $e->getMessage()) . "\n";
40 | } catch (TikTokRESTAPI\Exception\ProxyAuthException $e) {
41 | // Proxy auth data is missing or incorrect.
42 | echo sprintf('ProxyAuthException Catched: %s', $e->getMessage()) . "\n";
43 | } catch (TikTokRESTAPI\Exception\TooManyRequestsException $e) {
44 | // Too many requests sent to TikTok.
45 | echo sprintf('TooManyRequestsException Catched: %s', $e->getMessage()) . "\n";
46 | } catch (TikTokRESTAPI\Exception\NetworkException $e) {
47 | // Couldn't establish connection with REST API server
48 | echo sprintf('NetworkException Catched: %s', $e->getMessage()) . "\n";
49 | } catch (TikTokRESTAPI\Exception\TikTokException $e) {
50 | // Invalid argument, missing or invalid data in request
51 | echo sprintf('TikTokException Catched: %s', $e->getMessage()) . "\n";
52 | } catch (Exception $e) {
53 | echo sprintf('Exception Catched: %s', $e->getMessage()) . "\n";
54 | echo var_dump($e->getTrace());
55 | }
56 |
57 |
--------------------------------------------------------------------------------
/examples/getNoWatermarkUrl.php:
--------------------------------------------------------------------------------
1 | setCacheTimeout(3600);
18 |
19 | try {
20 | // Validate the TikTok video URL
21 | // This is an example how to get $video_url from Console/Terminal
22 | if (empty($video_url)) {
23 | echo 'Enter the TikTok video URL:';
24 | $video_url = trim(fgets(STDIN));
25 | }
26 |
27 | $resp = $tiktok->getNoWatermarkUrl($video_url);
28 | if ($resp->isOk() && $resp->isTiktok()) {
29 | $video_url = $resp->getTiktok()->getUrl();
30 | if (!empty($video_url)) {
31 | echo sprintf('Non-watermarked Video URL: %s', $video_url) . "\n";
32 | }
33 | }
34 | } catch (TikTokRESTAPI\Exception\BadRequestException $e) {
35 | // Request not performed because some data is missing or incorrect.
36 | echo sprintf('BadRequestException Catched: %s', $e->getMessage()) . "\n";
37 | } catch (TikTokRESTAPI\Exception\ForbiddenException $e) {
38 | // Request failed due to invalid, expired, revoked license or access to API is restricted.
39 | echo sprintf('ForbiddenException Catched: %s', $e->getMessage()) . "\n";
40 | } catch (TikTokRESTAPI\Exception\NotFoundException $e) {
41 | // Requested resource doesn't exist in TikTok.
42 | echo sprintf('NotFoundException Catched: %s', $e->getMessage()) . "\n";
43 | } catch (TikTokRESTAPI\Exception\ProxyAuthException $e) {
44 | // Proxy auth data is missing or incorrect.
45 | echo sprintf('ProxyAuthException Catched: %s', $e->getMessage()) . "\n";
46 | } catch (TikTokRESTAPI\Exception\TooManyRequestsException $e) {
47 | // Too many requests sent to TikTok.
48 | echo sprintf('TooManyRequestsException Catched: %s', $e->getMessage()) . "\n";
49 | } catch (TikTokRESTAPI\Exception\NetworkException $e) {
50 | // Couldn't establish connection with REST API server
51 | echo sprintf('NetworkException Catched: %s', $e->getMessage()) . "\n";
52 | } catch (TikTokRESTAPI\Exception\TikTokException $e) {
53 | // Invalid argument, missing or invalid data in request
54 | echo sprintf('TikTokException Catched: %s', $e->getMessage()) . "\n";
55 | } catch (Exception $e) {
56 | echo sprintf('Exception Catched: %s', $e->getMessage()) . "\n";
57 | echo var_dump($e->getTrace());
58 | }
--------------------------------------------------------------------------------
/src/Response/Model/Status.php:
--------------------------------------------------------------------------------
1 | 'string',
60 | 'allow_comment' => 'bool',
61 | 'private_status' => 'int',
62 | 'in_reviewing' => 'bool',
63 | 'reviewed' => 'int',
64 | 'review_result' => 'ReviewResult',
65 | 'is_delete' => 'bool',
66 | 'allow_share' => 'bool',
67 | 'self_see' => 'bool',
68 | 'is_prohibited' => 'bool',
69 | 'download_status' => 'int'
70 | ];
71 | }
72 |
--------------------------------------------------------------------------------
/examples/getNoWatermarkUrlByID.php:
--------------------------------------------------------------------------------
1 | setCacheTimeout(3600);
18 |
19 | try {
20 | // Validate the TikTok video ID
21 | // This is an example how to get $video_id from Console/Terminal
22 | if (empty($video_id)) {
23 | echo 'Enter the TikTok video ID:';
24 | $video_id = trim(fgets(STDIN));
25 | }
26 |
27 | $resp = $tiktok->getNoWatermarkUrlByID($video_id);
28 | if ($resp->isOk() && $resp->isTiktok()) {
29 | $video_url = $resp->getTiktok()->getUrl();
30 | if (!empty($video_url)) {
31 | echo sprintf('Non-watermarked Video URL: %s', $video_url) . "\n";
32 | }
33 | }
34 | } catch (TikTokRESTAPI\Exception\BadRequestException $e) {
35 | // Request not performed because some data is missing or incorrect.
36 | echo sprintf('BadRequestException Catched: %s', $e->getMessage()) . "\n";
37 | } catch (TikTokRESTAPI\Exception\ForbiddenException $e) {
38 | // Request failed due to invalid, expired, revoked license or access to API is restricted.
39 | echo sprintf('ForbiddenException Catched: %s', $e->getMessage()) . "\n";
40 | } catch (TikTokRESTAPI\Exception\NotFoundException $e) {
41 | // Requested resource doesn't exist in TikTok.
42 | echo sprintf('NotFoundException Catched: %s', $e->getMessage()) . "\n";
43 | } catch (TikTokRESTAPI\Exception\ProxyAuthException $e) {
44 | // Proxy auth data is missing or incorrect.
45 | echo sprintf('ProxyAuthException Catched: %s', $e->getMessage()) . "\n";
46 | } catch (TikTokRESTAPI\Exception\TooManyRequestsException $e) {
47 | // Too many requests sent to TikTok.
48 | echo sprintf('TooManyRequestsException Catched: %s', $e->getMessage()) . "\n";
49 | } catch (TikTokRESTAPI\Exception\NetworkException $e) {
50 | // Couldn't establish connection with REST API server
51 | echo sprintf('NetworkException Catched: %s', $e->getMessage()) . "\n";
52 | } catch (TikTokRESTAPI\Exception\TikTokException $e) {
53 | // Invalid argument, missing or invalid data in request
54 | echo sprintf('TikTokException Catched: %s', $e->getMessage()) . "\n";
55 | } catch (Exception $e) {
56 | echo sprintf('Exception Catched: %s', $e->getMessage()) . "\n";
57 | echo var_dump($e->getTrace());
58 | }
59 |
60 |
--------------------------------------------------------------------------------
/src/Response/Model/VideoControl.php:
--------------------------------------------------------------------------------
1 | 'int',
59 | 'draft_progress_bar' => 'int',
60 | 'timer_status' => 'int',
61 | 'allow_stitch' => 'bool',
62 | 'allow_download' => 'bool',
63 | 'show_progress_bar' => 'int',
64 | 'allow_duet' => 'bool',
65 | 'allow_react' => 'bool',
66 | 'prevent_download_type' => 'int',
67 | 'allow_dynamic_wallpaper' => 'bool',
68 | 'allow_music' => 'bool'
69 | ];
70 | }
71 |
--------------------------------------------------------------------------------
/examples/getVideoByID.php:
--------------------------------------------------------------------------------
1 | setCacheTimeout(3600);
18 |
19 | try {
20 | // Validate the TikTok video ID
21 | // This is an example how to get $video_id from Console/Terminal
22 | if (empty($video_id)) {
23 | echo 'Enter the TikTok video ID:';
24 | $video_id = trim(fgets(STDIN));
25 | }
26 |
27 | $resp = $tiktok->getVideoByID($video_id);
28 | if ($resp->isOk() && $resp->isTiktok() && $resp->getTiktok()->isAwemeDetail()) {
29 | $aweme_detail = $resp->getTiktok()->getAwemeDetail();
30 | if ($aweme_detail->isAuthor() && $aweme_detail->isStatistics()) {
31 | echo sprintf(
32 | 'Video published by @%s (%s) and have %s likes, %s plays and %s comments.',
33 | $aweme_detail->getAuthor()->getUniqueId(),
34 | $aweme_detail->getAuthor()->getNickname(),
35 | number_format($aweme_detail->getStatistics()->getDiggCount(), 0 , '.' , ' ' ),
36 | number_format($aweme_detail->getStatistics()->getPlayCount(), 0 , '.' , ' ' ),
37 | number_format($aweme_detail->getStatistics()->getCommentCount(), 0 , '.' , ' ' )
38 | ) . "\n";
39 | }
40 | }
41 | } catch (TikTokRESTAPI\Exception\BadRequestException $e) {
42 | // Request not performed because some data is missing or incorrect.
43 | echo sprintf('BadRequestException Catched: %s', $e->getMessage()) . "\n";
44 | } catch (TikTokRESTAPI\Exception\ForbiddenException $e) {
45 | // Request failed due to invalid, expired, revoked license or access to API is restricted.
46 | echo sprintf('ForbiddenException Catched: %s', $e->getMessage()) . "\n";
47 | } catch (TikTokRESTAPI\Exception\NotFoundException $e) {
48 | // Requested resource doesn't exist in TikTok.
49 | echo sprintf('NotFoundException Catched: %s', $e->getMessage()) . "\n";
50 | } catch (TikTokRESTAPI\Exception\ProxyAuthException $e) {
51 | // Proxy auth data is missing or incorrect.
52 | echo sprintf('ProxyAuthException Catched: %s', $e->getMessage()) . "\n";
53 | } catch (TikTokRESTAPI\Exception\TooManyRequestsException $e) {
54 | // Too many requests sent to TikTok.
55 | echo sprintf('TooManyRequestsException Catched: %s', $e->getMessage()) . "\n";
56 | } catch (TikTokRESTAPI\Exception\NetworkException $e) {
57 | // Couldn't establish connection with REST API server
58 | echo sprintf('NetworkException Catched: %s', $e->getMessage()) . "\n";
59 | } catch (TikTokRESTAPI\Exception\TikTokException $e) {
60 | // Invalid argument, missing or invalid data in request
61 | echo sprintf('TikTokException Catched: %s', $e->getMessage()) . "\n";
62 | } catch (Exception $e) {
63 | echo sprintf('Exception Catched: %s', $e->getMessage()) . "\n";
64 | echo var_dump($e->getTrace());
65 | }
66 |
67 |
--------------------------------------------------------------------------------
/examples/getVideoByUrl.php:
--------------------------------------------------------------------------------
1 | setCacheTimeout(3600);
18 |
19 | try {
20 | // Validate the TikTok video URL
21 | // This is an example how to get $video_url from Console/Terminal
22 | if (empty($video_url)) {
23 | echo 'Enter the TikTok video URL:';
24 | $video_url = trim(fgets(STDIN));
25 | }
26 |
27 | $resp = $tiktok->getVideoByID($video_url);
28 | if ($resp->isOk() && $resp->isTiktok() && $resp->getTiktok()->isAwemeDetail()) {
29 | $aweme_detail = $resp->getTiktok()->getAwemeDetail();
30 | if ($aweme_detail->isAuthor() && $aweme_detail->isStatistics()) {
31 | echo sprintf(
32 | 'Video published by @%s (%s) and have %s likes, %s plays and %s comments.',
33 | $aweme_detail->getAuthor()->getUniqueId(),
34 | $aweme_detail->getAuthor()->getNickname(),
35 | number_format($aweme_detail->getStatistics()->getDiggCount(), 0 , '.' , ' ' ),
36 | number_format($aweme_detail->getStatistics()->getPlayCount(), 0 , '.' , ' ' ),
37 | number_format($aweme_detail->getStatistics()->getCommentCount(), 0 , '.' , ' ' )
38 | ) . "\n";
39 | }
40 | }
41 | } catch (TikTokRESTAPI\Exception\BadRequestException $e) {
42 | // Request not performed because some data is missing or incorrect.
43 | echo sprintf('BadRequestException Catched: %s', $e->getMessage()) . "\n";
44 | } catch (TikTokRESTAPI\Exception\ForbiddenException $e) {
45 | // Request failed due to invalid, expired, revoked license or access to API is restricted.
46 | echo sprintf('ForbiddenException Catched: %s', $e->getMessage()) . "\n";
47 | } catch (TikTokRESTAPI\Exception\NotFoundException $e) {
48 | // Requested resource doesn't exist in TikTok.
49 | echo sprintf('NotFoundException Catched: %s', $e->getMessage()) . "\n";
50 | } catch (TikTokRESTAPI\Exception\ProxyAuthException $e) {
51 | // Proxy auth data is missing or incorrect.
52 | echo sprintf('ProxyAuthException Catched: %s', $e->getMessage()) . "\n";
53 | } catch (TikTokRESTAPI\Exception\TooManyRequestsException $e) {
54 | // Too many requests sent to TikTok.
55 | echo sprintf('TooManyRequestsException Catched: %s', $e->getMessage()) . "\n";
56 | } catch (TikTokRESTAPI\Exception\NetworkException $e) {
57 | // Couldn't establish connection with REST API server
58 | echo sprintf('NetworkException Catched: %s', $e->getMessage()) . "\n";
59 | } catch (TikTokRESTAPI\Exception\TikTokException $e) {
60 | // Invalid argument, missing or invalid data in request
61 | echo sprintf('TikTokException Catched: %s', $e->getMessage()) . "\n";
62 | } catch (Exception $e) {
63 | echo sprintf('Exception Catched: %s', $e->getMessage()) . "\n";
64 | echo var_dump($e->getTrace());
65 | }
66 |
67 |
--------------------------------------------------------------------------------
/examples/searchMusic.php:
--------------------------------------------------------------------------------
1 | setCacheTimeout(3600);
18 |
19 | try {
20 | if (empty($keyword)) {
21 | getKeyword:
22 | // Any text or keyword.
23 | // This is an example how to get $keyword from Console/Terminal
24 | echo 'Enter the text or keyword to search:';
25 | $keyword = trim(fgets(STDIN));
26 | }
27 |
28 | search:
29 | $resp = $tiktok->searchMusic($keyword);
30 |
31 | if ($resp->isOk() && $resp->isTiktok() && count($resp->getTiktok()->getMusic()) > 0) {
32 |
33 | $music_list = $resp->getTiktok()->getMusic();
34 | echo sprintf('Music found by keyword "%s":', $keyword) . "\n";
35 |
36 | foreach ($music_list as $key => $m) {
37 |
38 | $title = $m->getTitle();
39 | $author = $m->getAuthor();
40 | $album = $m->getAlbum();
41 |
42 | echo sprintf('%s. %s | Author: %s | Album: %s', $key + 1, $title, $author, $album) . "\n";
43 | }
44 | } else {
45 | echo sprintf('Music by keyword "%s" not found.', $keyword) . "\n";
46 | }
47 |
48 | echo 'Do you want to use search again?' . "\n";
49 | echo '1 - Yes' . "\n";
50 | echo '2 - No' . "\n";
51 | echo 'Your choice:';
52 | $choice = trim(fgets(STDIN));
53 | if ($choice == 1) {
54 | goto getKeyword;
55 | }
56 | } catch (TikTokRESTAPI\Exception\BadRequestException $e) {
57 | // Request not performed because some data is missing or incorrect.
58 | echo sprintf('BadRequestException Catched: %s', $e->getMessage()) . "\n";
59 | } catch (TikTokRESTAPI\Exception\ForbiddenException $e) {
60 | // Request failed due to invalid, expired, revoked license or access to API is restricted.
61 | echo sprintf('ForbiddenException Catched: %s', $e->getMessage()) . "\n";
62 | } catch (TikTokRESTAPI\Exception\NotFoundException $e) {
63 | // Requested resource doesn't exist in TikTok.
64 | echo sprintf('NotFoundException Catched: %s', $e->getMessage()) . "\n";
65 | } catch (TikTokRESTAPI\Exception\ProxyAuthException $e) {
66 | // Proxy auth data is missing or incorrect.
67 | echo sprintf('ProxyAuthException Catched: %s', $e->getMessage()) . "\n";
68 | } catch (TikTokRESTAPI\Exception\TooManyRequestsException $e) {
69 | // Too many requests sent to TikTok.
70 | echo sprintf('TooManyRequestsException Catched: %s', $e->getMessage()) . "\n";
71 | } catch (TikTokRESTAPI\Exception\NetworkException $e) {
72 | // Couldn't establish connection with REST API server
73 | echo sprintf('NetworkException Catched: %s', $e->getMessage()) . "\n";
74 | } catch (TikTokRESTAPI\Exception\TikTokException $e) {
75 | // Invalid argument, missing or invalid data in request
76 | echo sprintf('TikTokException Catched: %s', $e->getMessage()) . "\n";
77 | } catch (Exception $e) {
78 | echo sprintf('Exception Catched: %s', $e->getMessage()) . "\n";
79 | echo var_dump($e->getTrace());
80 | }
--------------------------------------------------------------------------------
/examples/searchVideo.php:
--------------------------------------------------------------------------------
1 | searchVideo($keyword, 30);
24 |
25 | if ($resp->isOk() && $resp->isTiktok() && count($resp->getTiktok()->getAwemeList()) > 0) {
26 |
27 | echo sprintf('Videos found by keyword "%s":', $keyword) . "\n";
28 |
29 | $video_list = $resp->getTiktok()->getAwemeList();
30 |
31 | foreach ($video_list as $key => $video) {
32 |
33 | $aweme_id = $video->getAwemeId();
34 | $nickname = $video->getAuthor()->getUniqueId();
35 | $fullname = $video->getAuthor()->getNickname();
36 | $inst_id = $video->getAuthor()->getInsId();
37 |
38 | if (!empty($inst_id)) {
39 | echo sprintf('Video %s by @%s (%s) | Instagram @%s', 'https://www.tiktok.com/@' . $nickname . '/video/' . $aweme_id, $nickname, $fullname, $inst_id) . "\n";
40 | } else {
41 | echo sprintf('Video %s by @%s (%s)', 'https://www.tiktok.com/@' . $nickname . '/video/' . $aweme_id, $nickname, $fullname) . "\n";
42 | }
43 | }
44 | }
45 |
46 | echo 'Do you want to use search again?' . "\n";
47 | echo '1 - Yes' . "\n";
48 | echo '2 - No' . "\n";
49 | echo 'Your choice:';
50 | $choice = trim(fgets(STDIN));
51 | if ($choice == 1) {
52 | goto getKeyword;
53 | }
54 | } catch (TikTokRESTAPI\Exception\BadRequestException $e) {
55 | // Request not performed because some data is missing or incorrect.
56 | echo sprintf('BadRequestException Catched: %s', $e->getMessage()) . "\n";
57 | } catch (TikTokRESTAPI\Exception\ForbiddenException $e) {
58 | // Request failed due to invalid, expired, revoked license or access to API is restricted.
59 | echo sprintf('ForbiddenException Catched: %s', $e->getMessage()) . "\n";
60 | } catch (TikTokRESTAPI\Exception\NotFoundException $e) {
61 | // Requested resource doesn't exist in TikTok.
62 | echo sprintf('NotFoundException Catched: %s', $e->getMessage()) . "\n";
63 | } catch (TikTokRESTAPI\Exception\ProxyAuthException $e) {
64 | // Proxy auth data is missing or incorrect.
65 | echo sprintf('ProxyAuthException Catched: %s', $e->getMessage()) . "\n";
66 | } catch (TikTokRESTAPI\Exception\TooManyRequestsException $e) {
67 | // Too many requests sent to TikTok.
68 | echo sprintf('TooManyRequestsException Catched: %s', $e->getMessage()) . "\n";
69 | } catch (TikTokRESTAPI\Exception\NetworkException $e) {
70 | // Couldn't establish connection with REST API server
71 | echo sprintf('NetworkException Catched: %s', $e->getMessage()) . "\n";
72 | } catch (TikTokRESTAPI\Exception\TikTokException $e) {
73 | // Invalid argument, missing or invalid data in request
74 | echo sprintf('TikTokException Catched: %s', $e->getMessage()) . "\n";
75 | } catch (Exception $e) {
76 | echo sprintf('Exception Catched: %s', $e->getMessage()) . "\n";
77 | echo var_dump($e->getTrace());
78 | }
79 |
80 |
--------------------------------------------------------------------------------
/src/Response/Model/ShareInfo.php:
--------------------------------------------------------------------------------
1 | 'string',
63 | 'share_signature_url' => 'string',
64 | 'share_quote' => 'string',
65 | 'share_desc_info' => 'string',
66 | 'share_url' => 'string',
67 | 'bool_persist' => 'int',
68 | 'share_title_other' => 'string',
69 | 'share_link_desc' => 'string',
70 | 'share_signature_desc' => 'string',
71 | 'whatsapp_desc' => 'string',
72 | 'share_desc' => 'string',
73 | 'share_title' => 'string'
74 | ];
75 | }
76 |
--------------------------------------------------------------------------------
/examples/searchHashtag.php:
--------------------------------------------------------------------------------
1 | setCacheTimeout(3600);
18 |
19 | try {
20 | if (empty($keyword)) {
21 | getKeyword:
22 | // Any text or keyword.
23 | // This is an example how to get $keyword from Console/Terminal
24 | echo 'Enter the text or keyword to search:';
25 | $keyword = trim(fgets(STDIN));
26 | }
27 |
28 | search:
29 | $resp = $tiktok->searchHashtag($keyword);
30 |
31 | if ($resp->isOk() && $resp->isTiktok() && $resp->getTiktok()->isChallengeList() && count($resp->getTiktok()->getChallengeList()) > 0) {
32 |
33 | echo sprintf('Hashtags found by keyword "%s":', $keyword) . "\n";
34 |
35 | $hashtags = $resp->getTiktok()->getChallengeList();
36 |
37 | foreach ($hashtags as $key => $h) {
38 |
39 | $hashtag = $h->getChallengeInfo()->getChaName();
40 | $use_count = number_format($h->getChallengeInfo()->getUseCount(), 0, '', ' ');
41 | $view_count = number_format($h->getChallengeInfo()->getViewCount(), 0, '', ' ');
42 |
43 | echo sprintf('%s. %s | Use Count: %s | View Count: %s', $key + 1, $hashtag, $use_count, $view_count) . "\n";
44 | }
45 | } else {
46 | echo sprintf('Hashtags by keyword "%s" not found.', $keyword) . "\n";
47 | }
48 |
49 | echo 'Do you want to use search again?' . "\n";
50 | echo '1 - Yes' . "\n";
51 | echo '2 - No' . "\n";
52 | echo 'Your choice:';
53 | $choice = trim(fgets(STDIN));
54 | if ($choice == 1) {
55 | goto getKeyword;
56 | }
57 | } catch (TikTokRESTAPI\Exception\BadRequestException $e) {
58 | // Request not performed because some data is missing or incorrect.
59 | echo sprintf('BadRequestException Catched: %s', $e->getMessage()) . "\n";
60 | } catch (TikTokRESTAPI\Exception\ForbiddenException $e) {
61 | // Request failed due to invalid, expired, revoked license or access to API is restricted.
62 | echo sprintf('ForbiddenException Catched: %s', $e->getMessage()) . "\n";
63 | } catch (TikTokRESTAPI\Exception\NotFoundException $e) {
64 | // Requested resource doesn't exist in TikTok.
65 | echo sprintf('NotFoundException Catched: %s', $e->getMessage()) . "\n";
66 | } catch (TikTokRESTAPI\Exception\ProxyAuthException $e) {
67 | // Proxy auth data is missing or incorrect.
68 | echo sprintf('ProxyAuthException Catched: %s', $e->getMessage()) . "\n";
69 | } catch (TikTokRESTAPI\Exception\TooManyRequestsException $e) {
70 | // Too many requests sent to TikTok.
71 | echo sprintf('TooManyRequestsException Catched: %s', $e->getMessage()) . "\n";
72 | } catch (TikTokRESTAPI\Exception\NetworkException $e) {
73 | // Couldn't establish connection with REST API server
74 | echo sprintf('NetworkException Catched: %s', $e->getMessage()) . "\n";
75 | } catch (TikTokRESTAPI\Exception\TikTokException $e) {
76 | // Invalid argument, missing or invalid data in request
77 | echo sprintf('TikTokException Catched: %s', $e->getMessage()) . "\n";
78 | } catch (Exception $e) {
79 | echo sprintf('Exception Catched: %s', $e->getMessage()) . "\n";
80 | echo var_dump($e->getTrace());
81 | }
--------------------------------------------------------------------------------
/examples/searchUser.php:
--------------------------------------------------------------------------------
1 | setCacheTimeout(3600);
18 |
19 | try {
20 | if (empty($keyword)) {
21 | getKeyword:
22 | // Any text or keyword.
23 | // This is an example how to get $keyword from Console/Terminal
24 | echo 'Enter the text or keyword to search:';
25 | $keyword = trim(fgets(STDIN));
26 | }
27 |
28 | search:
29 | $resp = $tiktok->searchUser($keyword);
30 |
31 | if ($resp->isOk() && $resp->isTiktok() && count($resp->getTiktok()->getUserList()) > 0) {
32 |
33 | $user_list = $resp->getTiktok()->getUserList();
34 | echo sprintf('Users found by keyword "%s":', $keyword) . "\n";
35 |
36 | foreach ($user_list as $key => $user) {
37 |
38 | $nickname = $user->getUserInfo()->getUniqueId();
39 | $fullname = $user->getUserInfo()->getNickname();
40 | $inst_id = $user->getUserInfo()->getInsId();
41 |
42 | if (!empty($inst_id)) {
43 | echo sprintf('@%s (%s) | Instagram @%s', $nickname, $fullname, $inst_id) . "\n";
44 | } else {
45 | echo sprintf('@%s (%s)', $nickname, $fullname) . "\n";
46 | }
47 | }
48 | } else {
49 | echo sprintf('Users by keyword "%s" not found.', $keyword) . "\n";
50 | }
51 |
52 | echo 'Do you want to use search again?' . "\n";
53 | echo '1 - Yes' . "\n";
54 | echo '2 - No' . "\n";
55 | echo 'Your choice:';
56 | $choice = trim(fgets(STDIN));
57 | if ($choice == 1) {
58 | goto getKeyword;
59 | }
60 | } catch (TikTokRESTAPI\Exception\BadRequestException $e) {
61 | // Request not performed because some data is missing or incorrect.
62 | echo sprintf('BadRequestException Catched: %s', $e->getMessage()) . "\n";
63 | } catch (TikTokRESTAPI\Exception\ForbiddenException $e) {
64 | // Request failed due to invalid, expired, revoked license or access to API is restricted.
65 | echo sprintf('ForbiddenException Catched: %s', $e->getMessage()) . "\n";
66 | } catch (TikTokRESTAPI\Exception\NotFoundException $e) {
67 | // Requested resource doesn't exist in TikTok.
68 | echo sprintf('NotFoundException Catched: %s', $e->getMessage()) . "\n";
69 | } catch (TikTokRESTAPI\Exception\ProxyAuthException $e) {
70 | // Proxy auth data is missing or incorrect.
71 | echo sprintf('ProxyAuthException Catched: %s', $e->getMessage()) . "\n";
72 | } catch (TikTokRESTAPI\Exception\TooManyRequestsException $e) {
73 | // Too many requests sent to TikTok.
74 | echo sprintf('TooManyRequestsException Catched: %s', $e->getMessage()) . "\n";
75 | } catch (TikTokRESTAPI\Exception\NetworkException $e) {
76 | // Couldn't establish connection with REST API server
77 | echo sprintf('NetworkException Catched: %s', $e->getMessage()) . "\n";
78 | } catch (TikTokRESTAPI\Exception\TikTokException $e) {
79 | // Invalid argument, missing or invalid data in request
80 | echo sprintf('TikTokException Catched: %s', $e->getMessage()) . "\n";
81 | } catch (Exception $e) {
82 | echo sprintf('Exception Catched: %s', $e->getMessage()) . "\n";
83 | echo var_dump($e->getTrace());
84 | }
85 |
86 |
--------------------------------------------------------------------------------
/examples/searchLive.php:
--------------------------------------------------------------------------------
1 | setCacheTimeout(3600);
18 |
19 | try {
20 | if (empty($keyword)) {
21 | getKeyword:
22 | // Any text or keyword.
23 | // This is an example how to get $keyword from Console/Terminal
24 | echo 'Enter the text or keyword to search:';
25 | $keyword = trim(fgets(STDIN));
26 | }
27 |
28 | search:
29 | $resp = $tiktok->searchLive($keyword);
30 |
31 | if ($resp->isOk() && $resp->hasTiktok() && $resp->getTiktok()->hasData() && count($resp->getTiktok()->getData()) > 0) {
32 |
33 | $lives = $resp->getTiktok()->getData();
34 | echo sprintf('Livestreams found by keyword "%s":', $keyword) . "\n";
35 |
36 | foreach ($lives as $key => $l) {
37 |
38 | $title = $l->getLives()->getAuthor()->getRoomTitle() !== "" ? $l->getLives()->getAuthor()->getRoomTitle() : "Empty Title";
39 | $nickname = $l->getLives()->getAuthor()->getNickname();
40 | $unique_id = $l->getLives()->getAuthor()->getUniqueId();
41 | $room_id = $l->getLives()->getAuthor()->getRoomId();
42 |
43 | echo sprintf('%s. %s | Author: %s (@%s) | Room ID: %s', $key + 1, $title, $nickname, $unique_id, $room_id) . "\n";
44 | }
45 | } else {
46 | echo sprintf('Livestreams by keyword "%s" not found.', $keyword) . "\n";
47 | }
48 |
49 | echo 'Do you want to use search again?' . "\n";
50 | echo '1 - Yes' . "\n";
51 | echo '2 - No' . "\n";
52 | echo 'Your choice:';
53 | $choice = trim(fgets(STDIN));
54 | if ($choice == 1) {
55 | goto getKeyword;
56 | }
57 | } catch (TikTokRESTAPI\Exception\BadRequestException $e) {
58 | // Request not performed because some data is missing or incorrect.
59 | echo sprintf('BadRequestException Catched: %s', $e->getMessage()) . "\n";
60 | } catch (TikTokRESTAPI\Exception\ForbiddenException $e) {
61 | // Request failed due to invalid, expired, revoked license or access to API is restricted.
62 | echo sprintf('ForbiddenException Catched: %s', $e->getMessage()) . "\n";
63 | } catch (TikTokRESTAPI\Exception\NotFoundException $e) {
64 | // Requested resource doesn't exist in TikTok.
65 | echo sprintf('NotFoundException Catched: %s', $e->getMessage()) . "\n";
66 | } catch (TikTokRESTAPI\Exception\ProxyAuthException $e) {
67 | // Proxy auth data is missing or incorrect.
68 | echo sprintf('ProxyAuthException Catched: %s', $e->getMessage()) . "\n";
69 | } catch (TikTokRESTAPI\Exception\TooManyRequestsException $e) {
70 | // Too many requests sent to TikTok.
71 | echo sprintf('TooManyRequestsException Catched: %s', $e->getMessage()) . "\n";
72 | } catch (TikTokRESTAPI\Exception\NetworkException $e) {
73 | // Couldn't establish connection with REST API server
74 | echo sprintf('NetworkException Catched: %s', $e->getMessage()) . "\n";
75 | } catch (TikTokRESTAPI\Exception\TikTokException $e) {
76 | // Invalid argument, missing or invalid data in request
77 | echo sprintf('TikTokException Catched: %s', $e->getMessage()) . "\n";
78 | } catch (Exception $e) {
79 | echo sprintf('Exception Catched: %s', $e->getMessage()) . "\n";
80 | echo var_dump($e->getTrace());
81 | }
--------------------------------------------------------------------------------
/src/Response/Model/Comment.php:
--------------------------------------------------------------------------------
1 | 'string',
79 | 'cid' => 'string',
80 | 'create_time' => 'int',
81 | 'digg_count' => 'int',
82 | 'is_author_digged' => 'bool',
83 | 'label_list' => '',
84 | 'reply_comment' => '',
85 | 'reply_id' => 'string',
86 | 'reply_to_reply_id' => 'string',
87 | 'status' => 'int',
88 | 'stick_position' => 'int',
89 | 'text' => 'string',
90 | 'text_extra' => 'TextExtra',
91 | 'user' => 'User',
92 | 'user_buried' => 'bool',
93 | 'user_digged' => 'int'
94 | ];
95 | }
96 |
--------------------------------------------------------------------------------
/src/Response/Model/TikTok.php:
--------------------------------------------------------------------------------
1 | 'string',
75 | 'url' => 'string',
76 | 'status_code' => 'int',
77 | 'aweme_detail' => 'AwemeDetail',
78 | 'comments' => 'Comment[]',
79 | 'cursor' => 'int',
80 | 'has_more' => 'int',
81 | 'total' => 'int',
82 | 'input_keyword' => 'string',
83 | 'user_list' => 'UserSearchItem[]',
84 | 'aweme_list' => 'AwemeListItem[]',
85 | 'music' => 'MusicSearchItem[]',
86 | 'data' => 'Data[]',
87 | 'challenge_list' => 'ChallengeList[]',
88 | 'user' => 'User'
89 | ];
90 | }
91 |
--------------------------------------------------------------------------------
/examples/getCommentsByID.php:
--------------------------------------------------------------------------------
1 | setCacheTimeout(3600);
18 |
19 | try {
20 | // Validate the TikTok video ID
21 | // This is an example how to get $video_id from Console/Terminal
22 | if (empty($video_id)) {
23 | getVideoID:
24 | echo 'Enter the TikTok video ID:';
25 | $video_id = trim(fgets(STDIN));
26 | }
27 |
28 | getComments:
29 | if (isset($cursor)) {
30 | $resp = $tiktok->getCommentsByID($video_id, $cursor);
31 | } else {
32 | $resp = $tiktok->getCommentsByID($video_id);
33 | }
34 |
35 | if ($resp->isOk() && $resp->isTiktok()) {
36 |
37 | $comments = $resp->getTiktok()->getComments();
38 |
39 | if (count($comments) > 0) {
40 | $total = $resp->getTiktok()->getTotal();
41 |
42 | if (isset($cursor)) {
43 | echo sprintf('Loading next %s comments.', number_format(count($comments), 0 , '.' , ' ' )) . "\n";
44 | } else {
45 | echo sprintf('Video has %s comments.', number_format($total, 0 , '.' , ' ' )) . "\n";
46 | echo sprintf('Loading last %s comments.', number_format(count($comments), 0 , '.' , ' ' )) . "\n";
47 | }
48 |
49 | foreach ($comments as $key => $comment) {
50 | echo sprintf('Comment by @%s (%s)', $comment->getUser()->getUniqueId(), $comment->getUser()->getNickname()) . "\n";
51 | echo sprintf('- %s', $comment->getText()) . "\n";
52 | }
53 |
54 | $hasMore = $resp->getTiktok()->getHasMore();
55 | $cursor = $resp->getTiktok()->getCursor();
56 |
57 | if ($hasMore) {
58 | echo 'Do you want to load more comments?' . "\n";
59 | echo '1 - Yes' . "\n";
60 | echo '2 - No' . "\n";
61 | echo '3 - Check another video' . "\n";
62 | echo 'Your choice:';
63 | $choice = trim(fgets(STDIN));
64 | if ($choice == 1) {
65 | goto getComments;
66 | } elseif ($choice == 3) {
67 | goto getVideoID;
68 | }
69 | } else {
70 | echo "All video comments nas been loaded.\n";
71 | }
72 | } else {
73 | echo "Video has no comments.\n";
74 | }
75 | }
76 | } catch (TikTokRESTAPI\Exception\BadRequestException $e) {
77 | // Request not performed because some data is missing or incorrect.
78 | echo sprintf('BadRequestException Catched: %s', $e->getMessage()) . "\n";
79 | } catch (TikTokRESTAPI\Exception\ForbiddenException $e) {
80 | // Request failed due to invalid, expired, revoked license or access to API is restricted.
81 | echo sprintf('ForbiddenException Catched: %s', $e->getMessage()) . "\n";
82 | } catch (TikTokRESTAPI\Exception\NotFoundException $e) {
83 | // Requested resource doesn't exist in TikTok.
84 | echo sprintf('NotFoundException Catched: %s', $e->getMessage()) . "\n";
85 | } catch (TikTokRESTAPI\Exception\ProxyAuthException $e) {
86 | // Proxy auth data is missing or incorrect.
87 | echo sprintf('ProxyAuthException Catched: %s', $e->getMessage()) . "\n";
88 | } catch (TikTokRESTAPI\Exception\TooManyRequestsException $e) {
89 | // Too many requests sent to TikTok.
90 | echo sprintf('TooManyRequestsException Catched: %s', $e->getMessage()) . "\n";
91 | } catch (TikTokRESTAPI\Exception\NetworkException $e) {
92 | // Couldn't establish connection with REST API server
93 | echo sprintf('NetworkException Catched: %s', $e->getMessage()) . "\n";
94 | } catch (TikTokRESTAPI\Exception\TikTokException $e) {
95 | // Invalid argument, missing or invalid data in request
96 | echo sprintf('TikTokException Catched: %s', $e->getMessage()) . "\n";
97 | } catch (Exception $e) {
98 | echo sprintf('Exception Catched: %s', $e->getMessage()) . "\n";
99 | echo var_dump($e->getTrace());
100 | }
101 |
102 |
--------------------------------------------------------------------------------
/examples/getCommentsByUrl.php:
--------------------------------------------------------------------------------
1 | setCacheTimeout(3600);
18 |
19 | try {
20 | // Validate the TikTok video Url
21 | // This is an example how to get $video_url from Console/Terminal
22 | if (empty($video_url)) {
23 | getVideoUrl:
24 | echo 'Enter the TikTok video Url:';
25 | $video_url = trim(fgets(STDIN));
26 | }
27 |
28 | getComments:
29 | if (isset($cursor)) {
30 | $resp = $tiktok->getCommentsByUrl($video_url, $cursor);
31 | } else {
32 | $resp = $tiktok->getCommentsByUrl($video_url);
33 | }
34 |
35 | if ($resp->isOk() && $resp->isTiktok()) {
36 |
37 | $comments = $resp->getTiktok()->getComments();
38 |
39 | if (count($comments) > 0) {
40 | $total = $resp->getTiktok()->getTotal();
41 |
42 | if (isset($cursor)) {
43 | echo sprintf('Loading next %s comments.', number_format(count($comments), 0 , '.' , ' ' )) . "\n";
44 | } else {
45 | echo sprintf('Video has %s comments.', number_format($total, 0 , '.' , ' ' )) . "\n";
46 | echo sprintf('Loading last %s comments.', number_format(count($comments), 0 , '.' , ' ' )) . "\n";
47 | }
48 |
49 | foreach ($comments as $key => $comment) {
50 | echo sprintf('Comment by @%s (%s)', $comment->getUser()->getUniqueId(), $comment->getUser()->getNickname()) . "\n";
51 | echo sprintf('- %s', $comment->getText()) . "\n";
52 | }
53 |
54 | $hasMore = $resp->getTiktok()->getHasMore();
55 | $cursor = $resp->getTiktok()->getCursor();
56 |
57 | if ($hasMore) {
58 | echo 'Do you want to load more comments?' . "\n";
59 | echo '1 - Yes' . "\n";
60 | echo '2 - No' . "\n";
61 | echo '3 - Check another video' . "\n";
62 | echo 'Your choice:';
63 | $choice = trim(fgets(STDIN));
64 | if ($choice == 1) {
65 | goto getComments;
66 | } elseif ($choice == 3) {
67 | goto getVideoUrl;
68 | }
69 | } else {
70 | echo "All video comments nas been loaded.\n";
71 | }
72 | } else {
73 | echo "Video has no comments.\n";
74 | }
75 | }
76 | } catch (TikTokRESTAPI\Exception\BadRequestException $e) {
77 | // Request not performed because some data is missing or incorrect.
78 | echo sprintf('BadRequestException Catched: %s', $e->getMessage()) . "\n";
79 | } catch (TikTokRESTAPI\Exception\ForbiddenException $e) {
80 | // Request failed due to invalid, expired, revoked license or access to API is restricted.
81 | echo sprintf('ForbiddenException Catched: %s', $e->getMessage()) . "\n";
82 | } catch (TikTokRESTAPI\Exception\NotFoundException $e) {
83 | // Requested resource doesn't exist in TikTok.
84 | echo sprintf('NotFoundException Catched: %s', $e->getMessage()) . "\n";
85 | } catch (TikTokRESTAPI\Exception\ProxyAuthException $e) {
86 | // Proxy auth data is missing or incorrect.
87 | echo sprintf('ProxyAuthException Catched: %s', $e->getMessage()) . "\n";
88 | } catch (TikTokRESTAPI\Exception\TooManyRequestsException $e) {
89 | // Too many requests sent to TikTok.
90 | echo sprintf('TooManyRequestsException Catched: %s', $e->getMessage()) . "\n";
91 | } catch (TikTokRESTAPI\Exception\NetworkException $e) {
92 | // Couldn't establish connection with REST API server
93 | echo sprintf('NetworkException Catched: %s', $e->getMessage()) . "\n";
94 | } catch (TikTokRESTAPI\Exception\TikTokException $e) {
95 | // Invalid argument, missing or invalid data in request
96 | echo sprintf('TikTokException Catched: %s', $e->getMessage()) . "\n";
97 | } catch (Exception $e) {
98 | echo sprintf('Exception Catched: %s', $e->getMessage()) . "\n";
99 | echo var_dump($e->getTrace());
100 | }
101 |
102 |
--------------------------------------------------------------------------------
/src/Response/Model/MusicSearchItem.php:
--------------------------------------------------------------------------------
1 | 'int',
87 | 'id_str' => 'string',
88 | 'title' => 'string',
89 | 'author' => 'string',
90 | 'album' => 'string',
91 | 'cover_large' => 'Media',
92 | 'cover_medium' => 'Media',
93 | 'cover_thumb' => 'Media',
94 | 'play_url' => 'Media',
95 | 'source_platform' => 'int',
96 | 'duration' => 'int',
97 | 'extra' => '',
98 | 'user_count' => 'int',
99 | 'position' => '',
100 | 'collect_stat' => 'int',
101 | 'status' => 'int',
102 | 'offline_desc' => 'string',
103 | 'owner_nickname' => 'string',
104 | ];
105 | }
106 |
--------------------------------------------------------------------------------
/src/Response/Model/ChaListItem.php:
--------------------------------------------------------------------------------
1 | 'User',
99 | 'banner_list' => '',
100 | 'cha_attrs' => '',
101 | 'cha_name' => 'string',
102 | 'cid' => 'string',
103 | 'collect_stat' => 'int',
104 | 'connect_music' => '',
105 | 'desc' => 'string',
106 | 'extra_attr' => 'ExtraAttr',
107 | 'hashtag_profile' => 'string',
108 | 'is_challenge' => 'int',
109 | 'is_commerce' => 'bool',
110 | 'is_pgcshow' => 'bool',
111 | 'schema' => 'string',
112 | 'search_highlight' => '',
113 | 'share_info' => 'ShareInfo',
114 | 'show_items' => '',
115 | 'sub_type' => 'int',
116 | 'type' => 'int',
117 | 'user_count' => 'int',
118 | 'view_count' => 'int'
119 | ];
120 | }
121 |
--------------------------------------------------------------------------------
/src/Response/Model/ChallengeInfo.php:
--------------------------------------------------------------------------------
1 | 'mixed',
103 | 'cha_attrs' => 'mixed',
104 | 'cha_name' => 'string',
105 | 'cid' => 'string',
106 | 'collect_stat' => 'int',
107 | 'connect_music' => 'mixed',
108 | 'desc' => 'string',
109 | 'extra_attr' => 'ExtraAttr',
110 | 'hashtag_profile' => 'string',
111 | 'is_challenge' => 'int',
112 | 'is_commerce' => 'bool',
113 | 'is_pgcshow' => 'bool',
114 | 'schema' => 'string',
115 | 'search_cha_name' => 'string',
116 | 'search_highlight' => 'mixed',
117 | 'share_info' => 'ShareInfo',
118 | 'show_items' => 'mixed',
119 | 'sub_type' => 'int',
120 | 'type' => 'int',
121 | 'use_count' => 'int',
122 | 'user_count' => 'int',
123 | 'view_count' => 'int',
124 | ];
125 | }
126 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # TikTok REST API wrapper for PHP
2 |
3 | 
4 | 
5 | 
6 |
7 | [
](https://app.getpostman.com/run-collection/24862082-d886cc87-4267-4e0c-b57a-2d083add50ad?action=collection%2Ffork&source=rip_markdown&collection-url=entityId%3D24862082-d886cc87-4267-4e0c-b57a-2d083add50ad%26entityType%3Dcollection%26workspaceId%3D24af3158-f1f6-4911-be7b-9c245435502f)
8 |
9 | [
](https://app.getpostman.com/run-collection/24862082-d886cc87-4267-4e0c-b57a-2d083add50ad?action=collection%2Ffork&source=rip_markdown&collection-url=entityId%3D24862082-d886cc87-4267-4e0c-b57a-2d083add50ad%26entityType%3Dcollection%26workspaceId%3D24af3158-f1f6-4911-be7b-9c245435502f)
10 |
11 | Easy to use [TikTok REST API](https://evelode.com/downloads/tiktok-rest-api/). Get TikTok public user data, feed, trends, hashtags, music, and non watermarked TikTok videos.
12 |
13 | Using our detailed multipurpose [API Documentation](https://evelode.com/tiktok-rest-api-documentation/) and following TikTok REST API wrapper for PHP you can explore and reach all TikTok REST API endpoints with ease.
14 |
15 | Try our [Trial license plan](https://evelode.com/downloads/tiktok-rest-api/) and test all API endpoints before buying a license.
16 |
17 | # Navigation
18 |
19 | - [Installation](#installation)
20 | - [Authentication](#authentication)
21 | - [Rate Limits](#rate-limits)
22 | - [License](#license)
23 | - [Support](#support)
24 | - [Endpoints](#endpoints)
25 | - [Examples](#examples)
26 | - [Video](#video)
27 | - [Search](#search)
28 | - [User](#user)
29 | - [Hashtag](#hashtag)
30 | - [Music](#music)
31 |
32 | # Installation
33 |
34 | If you want to install library **to exsiting project** using Composer:
35 |
36 | ```php
37 | cd /path-to-app/
38 | composer require evelode/tiktok-api-php
39 | ```
40 |
41 | - `/path-to-app/` project folder with existing `composer.json` file
42 |
43 | If you want to install library **to new project** using Composer:
44 |
45 | - If Composer not installed on your server/local machine, please follow this [installation guide](https://www.digitalocean.com/community/tutorials/how-to-install-and-use-composer-on-ubuntu-20-04)
46 |
47 | - Create blank file named as `composer.json` in project folder
48 |
49 | - Add following content to this file:
50 |
51 | ```php
52 | {
53 | "require": {
54 | "evelode/tiktok-api-php": "^1.0.0"
55 | }
56 | }
57 | ```
58 |
59 | - After that install library using the following command:
60 |
61 | ```php
62 | cd /path-to-app/
63 | composer update
64 | ```
65 |
66 | - `/path-to-app/` project folder with existing `composer.json` file
67 |
68 | # Authentication
69 |
70 | Authentication occurs by passing the license key value through a query string named `license_key`, which can be purchased [here](https://evelode.com/downloads/tiktok-rest-api/).
71 |
72 | API Server Url: `https://tiktok.evelode.com/tiktok-api`
73 |
74 | # Rate Limits
75 |
76 | The developer `license_key` gives the right to use all methods within the TikTok REST API within the limit of requests for a specific period. Requests limit based on your license length and will be flushed when you renew or upgrade your license. Empty or invalid responses doesn't affect requests counter.
77 |
78 | Every license plan also have a requests per minute rate limit. More info about license plans you can check [here](https://evelode.com/downloads/tiktok-rest-api/).
79 |
80 | # License
81 |
82 | You can buy a valid `license_key` for TikTok REST API [here](https://evelode.com/downloads/tiktok-rest-api/). This license based on period of usage and requests count.
83 |
84 | **Demo Access**: We offer a Trial access with limited requests count, if you want to test REST API you can get license key [here](https://evelode.com/downloads/tiktok-rest-api/). Trial license can't be renewed, but can be upgraded to another licenses types.
85 |
86 | # Support
87 |
88 | This is a developer's portal for TikTok REST API wrapper for PHP and should not be used for support. Please [contact us via website chat](https://evelode.com/#chatraChatExpanded) if you need to submit a support request or have any question about API functionality.
89 |
90 | # Endpoints
91 |
92 | Using our detailed [Postman collection](https://www.postman.com/evelode/workspace/evelode/api/e2ed8e20-0dbd-41a3-9363-092d810217ed?action=share&creator=24862082) you can explore and test all TikTok REST API endpoints in real time. Try our Trial license plan and test all API endpoints before buying a license.
93 |
94 | # Examples
95 |
96 | ## Video
97 |
98 | - [getNoWatermarkUrl.php](/examples/getNoWatermarkUrl.php)
99 | - [getNoWatermarkUrlByID.php](/examples/getNoWatermarkUrlByID.php)
100 | - [getVideoByID.php](/examples/getVideoByID.php)
101 | - [getVideoByUrl.php](/examples/getVideoByUrl.php)
102 | - [getUnshortenedUrl.php](/examples/getUnshortenedUrl.php)
103 | - [getCommentsByUrl.php](/examples/getCommentsByUrl.php)
104 | - [getCommentsByID.php](/examples/getCommentsByID.php)
105 |
106 | ## Search
107 |
108 | - [searchUser.php](/examples/searchUser.php)
109 | - [searchVideo.php](/examples/searchVideo.php)
110 | - [searchMusic.php](/examples/searchMusic.php)
111 | - [searchLive.php](/examples/searchLive.php)
112 | - [searchHashtag.php](/examples/searchHashtag.php)
113 |
114 | ## User
115 |
116 | ## Hashtag
117 |
118 | ## Music
119 |
--------------------------------------------------------------------------------
/src/Response/Model/Video.php:
--------------------------------------------------------------------------------
1 | 'bool',
115 | 'play_addr_h264' => 'Play',
116 | 'need_set_token' => 'bool',
117 | 'tags' => '',
118 | 'play_addr_bytevc1' => 'Play',
119 | 'ratio' => 'string',
120 | 'download_addr' => 'Download',
121 | 'bit_rate' => 'BitRate[]',
122 | 'duration' => 'int',
123 | 'cdn_url_expired' => 'int',
124 | 'misc_download_addrs' => '',
125 | 'meta' => '',
126 | 'cover' => 'Media',
127 | 'height' => 'string',
128 | 'animated_cover' => 'Media',
129 | 'is_callback' => 'bool',
130 | 'big_thumbs' => '',
131 | 'ai_dynamic_cover' => 'Media',
132 | 'ai_dynamic_cover_bak' => 'Media',
133 | 'play_addr' => 'Play',
134 | 'width' => 'int',
135 | 'dynamic_cover' => 'Media',
136 | 'origin_cover' => 'Media',
137 | 'is_bytevc1' => 'int',
138 | 'CoverTsp' => ''
139 | ];
140 | }
141 |
--------------------------------------------------------------------------------
/src/Response/Model/Author.php:
--------------------------------------------------------------------------------
1 | 'string',
143 | 'comment_filter_status' => 'int',
144 | 'short_id' => 'int',
145 | 'unique_id' => 'string',
146 | 'avatar_168x168' => 'Media',
147 | 'comment_setting' => 'int',
148 | 'custom_verify' => 'string',
149 | 'secret' => 'int',
150 | 'follow_status' => 'int',
151 | 'is_star' => 'bool',
152 | 'nickname' => 'string',
153 | 'avatar_medium' => 'Media',
154 | 'is_ad_fake' => 'bool',
155 | 'commerce_user_level' => 'int',
156 | 'prevent_download' => 'bool',
157 | 'avatar_thumb' => 'Media',
158 | 'duet_setting' => 'int',
159 | 'stitch_setting' => 'int',
160 | 'uid' => 'string',
161 | 'is_block' => 'bool',
162 | 'room_id' => 'int',
163 | 'room_title' => 'string',
164 | 'room_id_str' => 'string',
165 | 'search_user_name' => 'string',
166 | 'search_user_desc' => 'string',
167 | 'avatar_larger' => 'Media',
168 | 'follower_count' => 'int',
169 | 'language' => 'string',
170 | 'sec_uid' => 'string',
171 | 'ins_id' => 'string',
172 | 'enterprise_verify_reason' => 'string',
173 | 'download_setting' => 'int'
174 | ];
175 | }
176 |
--------------------------------------------------------------------------------
/src/Response/Model/Lives.php:
--------------------------------------------------------------------------------
1 | 'string',
176 | 'author' => 'Author',
177 | 'cha_list' => '',
178 | 'text_extra' => 'TextExtra',
179 | 'video_labels' => '',
180 | 'aweme_type' => 'int',
181 | 'image_infos' => '',
182 | 'position' => '',
183 | 'uniqid_position' => '',
184 | 'geofencing' => '',
185 | 'video_text' => '',
186 | 'label_top_text' => '',
187 | 'group_id' => 'string',
188 | 'nickname_position' => '',
189 | 'challenge_position' => '',
190 | 'long_video' => '',
191 | 'interaction_stickers' => '',
192 | 'origin_comment_ids' => '',
193 | 'commerce_config_data' => '',
194 | 'room' => 'Room',
195 | 'anchors' => '',
196 | 'rawdata' => '',
197 | 'hybrid_label' => '',
198 | 'geofencing_regions' => '',
199 | 'search_extra' => '',
200 | 'cover_labels' => '',
201 | 'mask_infos' => '',
202 | 'search_highlight' => '',
203 | 'green_screen_materials' => '',
204 | 'question_list' => '',
205 | 'content_desc_extra' => '',
206 | 'products_info' => '',
207 | 'branded_content_accounts' => '',
208 | 'tts_voice_ids' => '',
209 | 'reference_tts_voice_ids' => '',
210 | 'voice_filter_ids' => '',
211 | 'reference_voice_filter_ids' => '',
212 | 'muf_comment_info_v2' => '',
213 | 'behind_the_song_music_ids' => '',
214 | 'behind_the_song_video_music_ids' => '',
215 | 'operator_boost_info' => ''
216 | ];
217 | }
218 |
--------------------------------------------------------------------------------
/src/Response/Model/Music.php:
--------------------------------------------------------------------------------
1 | 'Media',
211 | 'tag_list' => '',
212 | 'video_duration' => 'int',
213 | 'cover_large' => 'Media',
214 | 'position' => '',
215 | 'sec_uid' => 'string',
216 | 'strong_beat_url' => 'Media',
217 | 'id' => 'int',
218 | 'owner_nickname' => 'string',
219 | 'binded_challenge_id' => 'int',
220 | 'duration' => 'int',
221 | 'shoot_duration' => 'int',
222 | 'mute_share' => 'bool',
223 | 'is_author_artist' => 'bool',
224 | 'matched_song' => 'MatchedSong',
225 | 'id_str' => 'string',
226 | 'author' => 'string',
227 | 'album' => 'string',
228 | 'is_original' => 'bool',
229 | 'author_deleted' => 'bool',
230 | 'author_position' => '',
231 | 'prevent_download' => 'bool',
232 | 'is_pgc' => 'bool',
233 | 'cover_medium' => 'Media',
234 | 'play_url' => 'Media',
235 | 'source_platform' => 'int',
236 | 'owner_id' => 'string',
237 | 'avatar_thumb' => 'Media',
238 | 'preview_start_time' => 'int',
239 | 'preview_end_time' => 'int',
240 | 'cover_thumb' => 'Media',
241 | 'user_count' => 'int',
242 | 'status' => 'int',
243 | 'owner_handle' => 'string',
244 | 'audition_duration' => 'int',
245 | 'title' => 'string',
246 | 'collect_stat' => 'int',
247 | 'offline_desc' => 'string',
248 | 'is_commerce_music' => 'bool',
249 | 'artists' => 'Artist[]',
250 | 'is_matched_metadata' => 'bool',
251 | 'matched_pgc_sound' => 'MatchedPgcSound',
252 | 'extra' => '',
253 | 'mid' => 'string',
254 | 'external_song_info' => 'ExternalSongInfo[]',
255 | 'is_audio_url_with_cookie' => 'bool',
256 | 'is_original_sound' => 'bool',
257 | 'lyric_short_position' => '',
258 | 'dmv_auto_show' => 'bool',
259 | ];
260 | }
261 |
--------------------------------------------------------------------------------
/src/Response/Model/AwemeDetail.php:
--------------------------------------------------------------------------------
1 | 'Statistics',
207 | 'is_vr' => 'bool',
208 | 'sort_label' => 'string',
209 | 'is_pgcshow' => 'bool',
210 | 'misc_info' => '',
211 | 'need_vs_entry' => 'bool',
212 | 'anchors' => 'Anchor[]',
213 | 'content_desc' => 'string',
214 | 'rate' => 'int',
215 | 'is_relieve' => 'bool',
216 | 'group_id' => 'string',
217 | 'prevent_download' => 'bool',
218 | 'distribute_type' => 'int',
219 | 'playlist_blocked' => 'bool',
220 | 'cmt_swt' => 'bool',
221 | 'label_top' => 'LabelTop',
222 | 'share_info' => 'ShareInfo',
223 | 'region' => 'string',
224 | 'stickers' => 'string',
225 | 'item_comment_settings' => 'int',
226 | 'sticker_detail' => 'StickerDetail',
227 | 'commerce_info' => 'CommerceInfo',
228 | 'desc' => 'string',
229 | 'item_stitch' => 'int',
230 | 'is_hash_tag' => 'int',
231 | 'collect_stat' => 'int',
232 | 'item_duet' => 'int',
233 | 'desc_language' => 'string',
234 | 'video_control' => 'VideoControl',
235 | 'has_vs_entry' => 'bool',
236 | 'aweme_acl' => 'AwemeAcl',
237 | 'risk_infos' => 'RiskInfos',
238 | 'share_url' => 'string',
239 | 'author' => 'Author',
240 | 'status' => 'Status',
241 | 'is_top' => 'int',
242 | 'aweme_type' => 'int',
243 | 'author_user_id' => 'int',
244 | 'bodydance_score' => 'int',
245 | 'create_time' => 'int',
246 | 'music' => 'Music',
247 | 'video' => 'Video',
248 | 'user_digged' => 'int',
249 | 'distance' => 'string',
250 | 'is_ads' => 'bool',
251 | 'without_watermark' => 'bool',
252 | 'follow_up_publish_from_id' => 'int',
253 | 'aweme_id' => 'string'
254 | ];
255 | }
256 |
--------------------------------------------------------------------------------
/src/Request.php:
--------------------------------------------------------------------------------
1 | _parent = $parent;
85 | $this->_endpoint = $endpoint;
86 | $this->_params['cache_timeout'] = $parent->cache_timeout;
87 | }
88 |
89 | /**
90 | * Add query param to request, overwriting any previous value.
91 | *
92 | * @param string $key
93 | * @param mixed $value
94 | *
95 | * @return self
96 | */
97 | public function addParam(
98 | $key,
99 | $value)
100 | {
101 | if ($value === true) {
102 | $value = 'true';
103 | } elseif ($value === false) {
104 | $value = 'false';
105 | }
106 | $this->_params[$key] = $value;
107 |
108 | return $this;
109 | }
110 |
111 | /**
112 | * Get query param of request.
113 | *
114 | * @return array
115 | */
116 | public function getParams()
117 | {
118 | return $this->_params;
119 | }
120 |
121 | /**
122 | * Add POST param to request, overwriting any previous value.
123 | *
124 | * @param string $key
125 | * @param mixed $value
126 | *
127 | * @return self
128 | */
129 | public function addPost(
130 | $key,
131 | $value)
132 | {
133 | if ($value === true) {
134 | $value = 'true';
135 | } elseif ($value === false) {
136 | $value = 'false';
137 | }
138 | $this->_posts[$key] = $value;
139 |
140 | return $this;
141 | }
142 |
143 | /**
144 | * Get POST param of request.
145 | *
146 | * @return array
147 | */
148 | public function getPosts()
149 | {
150 | return $this->_posts;
151 | }
152 |
153 | /**
154 | * Add custom header to request, overwriting any previous or default value.
155 | *
156 | * @param string $key
157 | * @param string $value
158 | *
159 | * @return self
160 | */
161 | public function addHeader(
162 | $key,
163 | $value)
164 | {
165 | $this->_headers[$key] = $value;
166 |
167 | return $this;
168 | }
169 |
170 | /**
171 | * Get header of request.
172 | *
173 | * @param string $key
174 | *
175 | * @return mixed
176 | */
177 | public function getHeader(
178 | $key)
179 | {
180 | if (!empty($this->_headers[$key])) {
181 | return $this->_headers[$key];
182 | }
183 | return false;
184 | }
185 |
186 | /**
187 | * Checks is header is added.
188 | *
189 | * @param string $key
190 | *
191 | * @return bool
192 | */
193 | public function hasHeader(
194 | $key)
195 | {
196 | if (isset($this->_headers[$key])) {
197 | return true;
198 | }
199 | return false;
200 | }
201 |
202 | /**
203 | * Get all headers of request.
204 | *
205 | * @param bool $keyValueArray
206 | *
207 | * @return mixed
208 | */
209 | public function getHeaders(
210 | $keyValueArray = false)
211 | {
212 | if ($keyValueArray === false) {
213 | $headers = [];
214 | foreach ($this->_headers as $key => $value) {
215 | $headers[] = sprintf('%s: %s', $key, $value);
216 | }
217 |
218 | return $headers;
219 | } else {
220 | return $this->_headers;
221 | }
222 | }
223 |
224 | /**
225 | * Set encoding of the request.
226 | *
227 | * @param string $encoding Request encoding type.
228 | *
229 | * @return self
230 | */
231 | public function setEncoding(
232 | $encoding)
233 | {
234 | $this->_encoding = $encoding;
235 |
236 | return $this;
237 | }
238 |
239 | /**
240 | * Get encoding of the request.
241 | *
242 | * @return string
243 | */
244 | public function getEncoding()
245 | {
246 | return $this->_encoding;
247 | }
248 |
249 | /**
250 | * Get raw response of the request.
251 | *
252 | * @param bool $bool
253 | *
254 | * @return self
255 | */
256 | public function getRaw(
257 | $bool = false)
258 | {
259 | $this->_getRaw = (bool) $bool;
260 |
261 | return $this;
262 | }
263 |
264 | /**
265 | * Is response is RAW response or not
266 | *
267 | * @return bool
268 | */
269 | public function isGetRaw()
270 | {
271 | return $this->_getRaw;
272 | }
273 |
274 | /**
275 | * Get request URL.
276 | *
277 | * @return string
278 | */
279 | public function getUrl()
280 | {
281 | if (strncmp($this->_endpoint, 'http:', 5) !== 0 && strncmp($this->_endpoint, 'https:', 6) !== 0) {
282 | return self::API_BASE . $this->_endpoint;
283 | }
284 | return $this->_endpoint;
285 | }
286 |
287 | /**
288 | * Get request body
289 | *
290 | * @return mixed
291 | */
292 | public function getBody()
293 | {
294 | if ($this->getEncoding() === 'json') {
295 | return json_encode($this->getPosts());
296 | } elseif ($this->getEncoding() === 'urlencode') {
297 | return http_build_query($this->getPosts());
298 | } else {
299 | return null;
300 | }
301 | }
302 |
303 | /**
304 | * Return safely JSON-decoded HTTP response.
305 | *
306 | * This uses a special decoder which handles 64-bit numbers correctly.
307 | *
308 | * @param bool $assoc When FALSE, decode to object instead of associative array.
309 | *
310 | * @throws \TikTokRESTAPI\Exception\TikTokException
311 | * @throws \TikTokRESTAPI\Exception\BadRequestException
312 | * @throws \TikTokRESTAPI\Exception\ForbiddenException
313 | * @throws \TikTokRESTAPI\Exception\NotFoundException
314 | * @throws \TikTokRESTAPI\Exception\ProxyAuthException
315 | * @throws \TikTokRESTAPI\Exception\TooManyRequestsException
316 | * @throws \Exception
317 | *
318 | * @return mixed
319 | */
320 | public function getResponse()
321 | {
322 | $curl_options = [];
323 |
324 | if ($this->getParams() !== null) {
325 | $url = $this->getUrl().'?'.urldecode(http_build_query($this->getParams()));
326 | } else {
327 | $url = $this->getUrl();
328 | }
329 |
330 | if ($this->getPosts() !== null) {
331 | if ($this->getEncoding() === 'json') {
332 | $this->addHeader('content-type', 'application/json; charset=utf-8');
333 | } else {
334 | $this->addHeader('content-type', 'application/x-www-form-urlencoded; charset=utf-8');
335 | }
336 | $curl_options[CURLOPT_POST] = true;
337 | $curl_options[CURLOPT_HTTPHEADER] = $this->getHeaders();
338 | $curl_options[CURLOPT_POSTFIELDS] = $this->getBody();
339 | $method = "POST";
340 | } else {
341 | $curl_options[CURLOPT_HTTPHEADER] = $this->getHeaders();
342 | $method = "GET";
343 | }
344 |
345 | $curl_options[CURLOPT_HEADER] = false;
346 | $curl_options[CURLOPT_ENCODING] = 'gzip';
347 | $curl_options[CURLOPT_RETURNTRANSFER] = true;
348 | $curl_options[CURLOPT_SSL_VERIFYHOST] = false;
349 | $curl_options[CURLOPT_SSL_VERIFYPEER] = false;
350 |
351 | // Make http client work with HTTP 2/0
352 | $curl_options[CURLOPT_HTTP_VERSION] = CURL_HTTP_VERSION_2_0;
353 | $curl_options[CURLOPT_SSLVERSION] = 1;
354 |
355 | $request_options = [
356 | "debug" => false,
357 | "verify" => file_exists('/etc/ssl/certs/cacert.pem') ? '/etc/ssl/certs/cacert.pem' : false,
358 | "timeout" => 30,
359 | 'decode_content' => true, // Decode gzip/deflate/etc HTTP responses.
360 | "curl" => $curl_options,
361 | // Tells Guzzle to stop throwing exceptions on non-"2xx" HTTP codes,
362 | // thus ensuring that it only triggers exceptions on socket errors!
363 | // We'll instead MANUALLY be throwing on certain other HTTP codes.
364 | 'http_errors' => false
365 | ];
366 |
367 | // Request debug output
368 | if ($this->_parent->debug === true) {
369 | $this->pre_debug();
370 | }
371 |
372 | // Perform the request to API server
373 | try {
374 | $client = new \GuzzleHttp\Client();
375 | $response = $client->request($method, $url, $request_options);
376 | } catch (\Exception $e) {
377 | // Re-wrap Guzzle's exception using our own NetworkException.
378 | throw new NetworkException($e);
379 | }
380 |
381 | // Response debug output
382 | if ($this->_parent->debug === true) {
383 | $this->post_debug($response);
384 | }
385 |
386 | // Get RAW response body
387 | $rawResponse = (string) $response->getBody();
388 |
389 | // Attempt to decode the raw JSON to an array
390 | $json = $this->api_body_decode($rawResponse, true);
391 |
392 | // Detect HTTP status codes in the response
393 | $httpCode = $response->getStatusCode();
394 |
395 | // Trying to identify message in response
396 | $message = null;
397 | if (!empty($json['message'])) {
398 | $message = $json['message'];
399 | }
400 |
401 | // Iterate in HTTP status codes and throw correct exception
402 | switch ($httpCode) {
403 | case 200: // Request performed successfully.
404 | break;
405 | case 400: // Request not performed because some data is missing or incorrect.
406 | if (!empty($message)) {
407 | throw new BadRequestException($message);
408 | } else {
409 | throw new BadRequestException("Request not performed because some data is missing or incorrect.");
410 | }
411 | break;
412 | case 403: // Request failed due to invalid, expired, revoked license or access to API is restricted.
413 | if (!empty($message)) {
414 | throw new ForbiddenException($message);
415 | } else {
416 | throw new ForbiddenException("Request failed due to invalid, expired, revoked license or access to API is restricted.");
417 | }
418 | break;
419 | case 404: // Requested resource doesn't exist in TikTok.
420 | if (!empty($message)) {
421 | throw new NotFoundException($message);
422 | } else {
423 | throw new NotFoundException("Requested resource doesn't exist in TikTok.");
424 | }
425 | break;
426 | case 407: // Proxy auth data is missing or incorrect.
427 | if (!empty($message)) {
428 | throw new ProxyAuthException($message);
429 | } else {
430 | throw new ProxyAuthException("Proxy auth data is missing or incorrect.");
431 | }
432 | break;
433 | case 429: // Too many requests sent to TikTok.
434 | if (!empty($message)) {
435 | throw new TooManyRequestsException($message);
436 | } else {
437 | throw new TooManyRequestsException("Too many requests sent to TikTok.");
438 | }
439 | break;
440 | default: // Other errors
441 | if (!empty($message)) {
442 | throw new TikTokException($message);
443 | } else {
444 | throw new TikTokException($e->getMessage());
445 | }
446 | break;
447 | }
448 |
449 | if ($this->isGetRaw()) {
450 | return $rawResponse;
451 | }
452 |
453 | return $json;
454 | }
455 |
456 | /**
457 | * Print request, if debug mode is enabled
458 | */
459 | public function pre_debug()
460 | {
461 | echo "\033[1;35;m[REQUEST]\n";
462 |
463 | $method = $this->getPosts() === null ? 'GET' : 'POST';
464 | if ($this->getParams() !== null) {
465 | echo "\033[1;33;m".strtoupper($method).": \033[0m".$this->getUrl().'?'.urldecode(http_build_query($this->getParams()))."\n";
466 | } else {
467 | echo "\033[1;33;m".strtoupper($method).": \033[0m".$this->getUrl()."\n";
468 | }
469 |
470 | echo "\033[1;35;mHEADERS:\n";
471 | foreach ($this->getHeaders() as $index => $value) {
472 | echo $value . "\n";
473 | }
474 |
475 | echo "\033[1;35;mENCODING: \033[0m".$this->getEncoding()."\n";
476 |
477 | if ($this->getPosts() !== null) {
478 | echo "\033[1;35;mDATA: \033[0m".$this->getBody()."\n\n";
479 | }
480 | }
481 |
482 | /**
483 | * Print response, if debug mode is enabled
484 | */
485 | public function post_debug(
486 | $response)
487 | {
488 | echo "\033[1;35;m[RESPONSE]\n";
489 | echo "\033[1;32;mSTATUS: \033[0m".$response->getStatusCode()."\n";
490 | if (!empty($response->getBody())) {
491 | // Human-Readable Response
492 | $rawResponse = (string) $response->getBody();
493 | $json = $this->api_body_decode($rawResponse, false);
494 | if (is_object($json)) {
495 | $prettyJson = @json_encode(
496 | $json,
497 | JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE
498 | );
499 | if ($prettyJson !== false) {
500 | echo "\033[1;32;mRESPONSE: \033[0m".$prettyJson."\n\n";
501 | } else {
502 | echo "\033[1;32;mRESPONSE: \033[0m".$response->getBody()->getContents()."\n\n";
503 | }
504 | } else {
505 | echo "\033[1;32;mRESPONSE: \033[0m".$response->getBody()->getContents()."\n\n";
506 | }
507 | } else {
508 | echo "\033[1;32;mRESPONSE:\n\n";
509 | }
510 | }
511 |
512 | /**
513 | * Decode a JSON reply from TikTok's API.
514 | *
515 | * WARNING: EXTREMELY IMPORTANT! NEVER, *EVER* USE THE BASIC "json_decode"
516 | * ON API REPLIES! ALWAYS USE THIS METHOD INSTEAD, TO ENSURE PROPER DECODING
517 | * OF BIG NUMBERS! OTHERWISE YOU'LL TRUNCATE VARIOUS INSTAGRAM API FIELDS!
518 | *
519 | * @param string $json The body (JSON string) of the API response.
520 | * @param bool $assoc When FALSE, decode to object instead of associative array.
521 | *
522 | * @return object|array|null Object if assoc false, Array if assoc true,
523 | * or NULL if unable to decode JSON.
524 | */
525 | public static function api_body_decode(
526 | $json,
527 | $assoc = true)
528 | {
529 | return @json_decode($json, $assoc, 512, JSON_BIGINT_AS_STRING);
530 | }
531 | }
--------------------------------------------------------------------------------
/src/TikTok.php:
--------------------------------------------------------------------------------
1 | licenseKey = $licenseKey;
44 | $this->debug = $debug;
45 | }
46 |
47 | /**
48 | * Set the API cache timeout
49 | *
50 | * By default we use caching system with 3600 seconds window to speed up similar requests to API.
51 | * If you want to disable caching, you can set 0 here.
52 | *
53 | * @param int $value Cache timeout in seconds
54 | */
55 | public function setCacheTimeout(
56 | $value)
57 | {
58 | $value = (int) $value;
59 | if ($value >= 0) {
60 | $this->cache_timeout = $value;
61 | }
62 | }
63 |
64 | /**
65 | * Set the API cache timeout back to default value
66 | *
67 | * By default we use caching system with 3600 seconds window to speed up similar requests to API.
68 | */
69 | public function unsetCacheTimeout()
70 | {
71 | $this->cache_timeout = 3600;
72 | }
73 |
74 | /**
75 | * Get non watermarked video URL.
76 | *
77 | * @param string $video_url TikTok video URL.
78 | *
79 | * @throws \TikTokRESTAPI\Exception\TikTokException
80 | * @throws \TikTokRESTAPI\Exception\BadRequestException
81 | * @throws \TikTokRESTAPI\Exception\ForbiddenException
82 | * @throws \TikTokRESTAPI\Exception\NotFoundException
83 | * @throws \TikTokRESTAPI\Exception\ProxyAuthException
84 | * @throws \TikTokRESTAPI\Exception\TooManyRequestsException
85 | * @throws \Exception
86 | *
87 | * @return \TikTokRESTAPI\Response\APIResponse
88 | */
89 | public function getNoWatermarkUrl(
90 | $video_url = '')
91 | {
92 | if (empty($video_url)) {
93 | throw new TikTokException("Empty video URL.");
94 | }
95 |
96 | $response = $this->request('getNoWatermarkUrl')
97 | ->addParam('license_key', $this->licenseKey)
98 | ->addParam('video_url', $video_url)
99 | ->getResponse();
100 |
101 | return new Response\APIResponse($response);
102 | }
103 |
104 | /**
105 | * Get non watermarked video url by video ID.
106 | *
107 | * @param string $video_id TikTok video ID.
108 | *
109 | * @throws \TikTokRESTAPI\Exception\TikTokException
110 | * @throws \TikTokRESTAPI\Exception\BadRequestException
111 | * @throws \TikTokRESTAPI\Exception\ForbiddenException
112 | * @throws \TikTokRESTAPI\Exception\NotFoundException
113 | * @throws \TikTokRESTAPI\Exception\ProxyAuthException
114 | * @throws \TikTokRESTAPI\Exception\TooManyRequestsException
115 | * @throws \Exception
116 | *
117 | * @return \TikTokRESTAPI\Response\APIResponse
118 | */
119 | public function getNoWatermarkUrlByID(
120 | $video_id = '')
121 | {
122 | if (empty($video_id)) {
123 | throw new TikTokException("Empty video ID.");
124 | }
125 |
126 | $response = $this->request('getNoWatermarkUrlByID')
127 | ->addParam('license_key', $this->licenseKey)
128 | ->addParam('video_id', $video_id)
129 | ->getResponse();
130 |
131 | return new Response\APIResponse($response);
132 | }
133 |
134 | /**
135 | * Get video info by ID.
136 | *
137 | * @param string $video_id TikTok video ID.
138 | *
139 | * @throws \TikTokRESTAPI\Exception\TikTokException
140 | * @throws \TikTokRESTAPI\Exception\BadRequestException
141 | * @throws \TikTokRESTAPI\Exception\ForbiddenException
142 | * @throws \TikTokRESTAPI\Exception\NotFoundException
143 | * @throws \TikTokRESTAPI\Exception\ProxyAuthException
144 | * @throws \TikTokRESTAPI\Exception\TooManyRequestsException
145 | * @throws \Exception
146 | *
147 | * @return \TikTokRESTAPI\Response\APIResponse
148 | */
149 | public function getVideoByID(
150 | $video_id = '')
151 | {
152 | if (empty($video_id)) {
153 | throw new TikTokException("Empty video ID.");
154 | }
155 |
156 | $response = $this->request('getVideoByID')
157 | ->addParam('license_key', $this->licenseKey)
158 | ->addParam('video_id', $video_id)
159 | ->getResponse();
160 |
161 | return new Response\APIResponse($response);
162 | }
163 |
164 | /**
165 | * Get video info by URL
166 | *
167 | * @param string $video_url TikTok video URL.
168 | *
169 | * @throws \TikTokRESTAPI\Exception\TikTokException
170 | * @throws \TikTokRESTAPI\Exception\BadRequestException
171 | * @throws \TikTokRESTAPI\Exception\ForbiddenException
172 | * @throws \TikTokRESTAPI\Exception\NotFoundException
173 | * @throws \TikTokRESTAPI\Exception\ProxyAuthException
174 | * @throws \TikTokRESTAPI\Exception\TooManyRequestsException
175 | * @throws \Exception
176 | *
177 | * @return \TikTokRESTAPI\Response\APIResponse
178 | */
179 | public function getVideoByUrl(
180 | $video_url = '')
181 | {
182 | if (empty($video_url)) {
183 | throw new TikTokException("Empty video URL.");
184 | }
185 |
186 | $response = $this->request('getVideoByUrl')
187 | ->addParam('license_key', $this->licenseKey)
188 | ->addParam('video_url', $video_url)
189 | ->getResponse();
190 |
191 | return new Response\APIResponse($response);
192 | }
193 |
194 | /**
195 | * Convert short TikTok video URL to full TikTok video URL
196 | *
197 | * @param string $video_url TikTok video URL.
198 | *
199 | * @throws \TikTokRESTAPI\Exception\TikTokException
200 | * @throws \TikTokRESTAPI\Exception\BadRequestException
201 | * @throws \TikTokRESTAPI\Exception\ForbiddenException
202 | * @throws \TikTokRESTAPI\Exception\NotFoundException
203 | * @throws \TikTokRESTAPI\Exception\ProxyAuthException
204 | * @throws \TikTokRESTAPI\Exception\TooManyRequestsException
205 | * @throws \Exception
206 | *
207 | * @return \TikTokRESTAPI\Response\APIResponse
208 | */
209 | public function getUnshortenedUrl(
210 | $video_url = '')
211 | {
212 | if (empty($video_url)) {
213 | throw new TikTokException("Empty video URL.");
214 | }
215 |
216 | $response = $this->request('getUnshortenedUrl')
217 | ->addParam('license_key', $this->licenseKey)
218 | ->addParam('video_url', $video_url)
219 | ->getResponse();
220 |
221 | return new Response\APIResponse($response);
222 | }
223 |
224 | /**
225 | * Get comments list by video URL
226 | *
227 | * @param string $video_url TikTok video URL.
228 | * @param string $cursor Used for scrolling (pagination) in comments items, you can get cursor value from the previous response.
229 | * @param int $count Number of comments you want to get. For example: 30.
230 | *
231 | * @throws \TikTokRESTAPI\Exception\TikTokException
232 | * @throws \TikTokRESTAPI\Exception\BadRequestException
233 | * @throws \TikTokRESTAPI\Exception\ForbiddenException
234 | * @throws \TikTokRESTAPI\Exception\NotFoundException
235 | * @throws \TikTokRESTAPI\Exception\ProxyAuthException
236 | * @throws \TikTokRESTAPI\Exception\TooManyRequestsException
237 | * @throws \Exception
238 | *
239 | * @return \TikTokRESTAPI\Response\APIResponse
240 | */
241 | public function getCommentsByUrl(
242 | $video_url = '',
243 | $cursor = '',
244 | $count = 30)
245 | {
246 | if (empty($video_url)) {
247 | throw new TikTokException("Empty video URL.");
248 | }
249 |
250 | $response = $this->request('getCommentsByUrl')
251 | ->addParam('license_key', $this->licenseKey)
252 | ->addParam('video_url', $video_url)
253 | ->addParam('cursor', $cursor)
254 | ->addParam('count', $count)
255 | ->getResponse();
256 |
257 | return new Response\APIResponse($response);
258 | }
259 |
260 | /**
261 | * Get comments list by video ID
262 | *
263 | * @param string $video_id TikTok video ID.
264 | * @param string $cursor Used for scrolling (pagination) in comments items, you can get cursor value from the previous response.
265 | * @param int $count Number of comments you want to get. For example: 30.
266 | *
267 | * @throws \TikTokRESTAPI\Exception\TikTokException
268 | * @throws \TikTokRESTAPI\Exception\BadRequestException
269 | * @throws \TikTokRESTAPI\Exception\ForbiddenException
270 | * @throws \TikTokRESTAPI\Exception\NotFoundException
271 | * @throws \TikTokRESTAPI\Exception\ProxyAuthException
272 | * @throws \TikTokRESTAPI\Exception\TooManyRequestsException
273 | * @throws \Exception
274 | *
275 | * @return \TikTokRESTAPI\Response\APIResponse
276 | */
277 | public function getCommentsByID(
278 | $video_id = '',
279 | $cursor = '',
280 | $count = 30)
281 | {
282 | if (empty($video_id)) {
283 | throw new TikTokException("Empty video ID.");
284 | }
285 |
286 | $response = $this->request('getCommentsByID')
287 | ->addParam('license_key', $this->licenseKey)
288 | ->addParam('video_id', $video_id)
289 | ->addParam('cursor', $cursor)
290 | ->addParam('count', $count)
291 | ->getResponse();
292 |
293 | return new Response\APIResponse($response);
294 | }
295 |
296 | /**
297 | * Search for user by keyword
298 | *
299 | * @param string $keyword Any text or keyword
300 | * @param string $cursor Used for scrolling (pagination) in the list of users, you can get cursor value from the previous response.
301 | * @param int $count Number of users you want to get. For example: 10.
302 | *
303 | * @throws \TikTokRESTAPI\Exception\TikTokException
304 | * @throws \TikTokRESTAPI\Exception\BadRequestException
305 | * @throws \TikTokRESTAPI\Exception\ForbiddenException
306 | * @throws \TikTokRESTAPI\Exception\NotFoundException
307 | * @throws \TikTokRESTAPI\Exception\ProxyAuthException
308 | * @throws \TikTokRESTAPI\Exception\TooManyRequestsException
309 | * @throws \Exception
310 | *
311 | * @return \TikTokRESTAPI\Response\APIResponse
312 | */
313 | public function searchUser(
314 | $keyword = '',
315 | $cursor = '',
316 | $count = 10)
317 | {
318 | if (empty($keyword)) {
319 | throw new TikTokException("Empty keyword.");
320 | }
321 |
322 | $response = $this->request('searchUser')
323 | ->addParam('license_key', $this->licenseKey)
324 | ->addParam('keyword', $keyword)
325 | ->addParam('cursor', $cursor)
326 | ->addParam('count', $count)
327 | ->getResponse();
328 |
329 | return new Response\APIResponse($response);
330 | }
331 |
332 | /**
333 | * Search for video by keyword
334 | *
335 | * @param string $keyword Any text or keyword
336 | * @param string $cursor Used for scrolling (pagination) in the list of videos, you can get cursor value from the previous response.
337 | * @param int $count Number of videos you want to get. For example: 10.
338 | * @param string $date_posted How long ago was the video posted. Valid values: 'yesterday', 'this-week', 'this-month', 'last-3-months', 'last-6-months' and 'all-time'.
339 | * @param string $sort_by Sort videos by metrics. Valid values: 'most-liked' or 'relevance'.
340 | *
341 | * @throws \TikTokRESTAPI\Exception\TikTokException
342 | * @throws \TikTokRESTAPI\Exception\BadRequestException
343 | * @throws \TikTokRESTAPI\Exception\ForbiddenException
344 | * @throws \TikTokRESTAPI\Exception\NotFoundException
345 | * @throws \TikTokRESTAPI\Exception\ProxyAuthException
346 | * @throws \TikTokRESTAPI\Exception\TooManyRequestsException
347 | * @throws \Exception
348 | *
349 | * @return \TikTokRESTAPI\Response\APIResponse
350 | */
351 | public function searchVideo(
352 | $keyword = '',
353 | $cursor = '',
354 | $count = 10,
355 | $date_posted = 'all-time',
356 | $sort_by = 'relevance')
357 | {
358 | if (empty($keyword)) {
359 | throw new TikTokException("Empty keyword.");
360 | }
361 |
362 | $response = $this->request('searchVideo')
363 | ->addParam('license_key', $this->licenseKey)
364 | ->addParam('keyword', $keyword)
365 | ->addParam('cursor', $cursor)
366 | ->addParam('count', $count)
367 | ->addParam('date_posted', $date_posted)
368 | ->addParam('sort_by', $sort_by)
369 | ->getResponse();
370 |
371 | return new Response\APIResponse($response);
372 | }
373 |
374 | /**
375 | * Search for music by keyword
376 | *
377 | * @param string $keyword Any text or keyword
378 | * @param string $cursor Used for scrolling (pagination) in the list of music tracks, you can get cursor value from the previous response.
379 | * @param int $count Number of music tracks you want to get. For example: 10.
380 | *
381 | * @throws \TikTokRESTAPI\Exception\TikTokException
382 | * @throws \TikTokRESTAPI\Exception\BadRequestException
383 | * @throws \TikTokRESTAPI\Exception\ForbiddenException
384 | * @throws \TikTokRESTAPI\Exception\NotFoundException
385 | * @throws \TikTokRESTAPI\Exception\ProxyAuthException
386 | * @throws \TikTokRESTAPI\Exception\TooManyRequestsException
387 | * @throws \Exception
388 | *
389 | * @return \TikTokRESTAPI\Response\APIResponse
390 | */
391 | public function searchMusic(
392 | $keyword = '',
393 | $cursor = '',
394 | $count = 10)
395 | {
396 | if (empty($keyword)) {
397 | throw new TikTokException("Empty keyword.");
398 | }
399 |
400 | $response = $this->request('searchMusic')
401 | ->addParam('license_key', $this->licenseKey)
402 | ->addParam('keyword', $keyword)
403 | ->addParam('cursor', $cursor)
404 | ->addParam('count', $count)
405 | ->getResponse();
406 |
407 | return new Response\APIResponse($response);
408 | }
409 |
410 | /**
411 | * Search for live by keyword
412 | *
413 | * @param string $keyword Any text or keyword
414 | * @param string $offset Used for scrolling (pagination) in the list of lives, you can get cursor value from the previous response.
415 | * @param string $count Number of lives you want to get. For example: 10.
416 | *
417 | * @throws \TikTokRESTAPI\Exception\TikTokException
418 | * @throws \TikTokRESTAPI\Exception\BadRequestException
419 | * @throws \TikTokRESTAPI\Exception\ForbiddenException
420 | * @throws \TikTokRESTAPI\Exception\NotFoundException
421 | * @throws \TikTokRESTAPI\Exception\ProxyAuthException
422 | * @throws \TikTokRESTAPI\Exception\TooManyRequestsException
423 | * @throws \Exception
424 | *
425 | * @return \TikTokRESTAPI\Response\APIResponse
426 | */
427 | public function searchLive(
428 | $keyword = '',
429 | $offset = '',
430 | $count = 10)
431 | {
432 | if (empty($keyword)) {
433 | throw new TikTokException("Empty keyword.");
434 | }
435 |
436 | $response = $this->request('searchLive')
437 | ->addParam('license_key', $this->licenseKey)
438 | ->addParam('keyword', $keyword)
439 | ->addParam('offset', $offset)
440 | ->addParam('count', $count)
441 | ->getResponse();
442 |
443 | return new Response\APIResponse($response);
444 | }
445 |
446 | /**
447 | * Search for hashtag by keyword
448 | *
449 | * @param string $keyword Any text or keyword
450 | * @param string $cursor Used for scrolling (pagination) in the list of lives, you can get cursor value from the previous response.
451 | * @param string $count Number of lives you want to get. For example: 10.
452 | *
453 | * @throws \TikTokRESTAPI\Exception\TikTokException
454 | * @throws \TikTokRESTAPI\Exception\BadRequestException
455 | * @throws \TikTokRESTAPI\Exception\ForbiddenException
456 | * @throws \TikTokRESTAPI\Exception\NotFoundException
457 | * @throws \TikTokRESTAPI\Exception\ProxyAuthException
458 | * @throws \TikTokRESTAPI\Exception\TooManyRequestsException
459 | * @throws \Exception
460 | *
461 | * @return \TikTokRESTAPI\Response\APIResponse
462 | */
463 | public function searchHashtag(
464 | $keyword = '',
465 | $cursor = '',
466 | $count = 10)
467 | {
468 | if (empty($keyword)) {
469 | throw new TikTokException("Empty keyword.");
470 | }
471 |
472 | $response = $this->request('searchHashtag')
473 | ->addParam('license_key', $this->licenseKey)
474 | ->addParam('keyword', $keyword)
475 | ->addParam('cursor', $cursor)
476 | ->addParam('count', $count)
477 | ->getResponse();
478 |
479 | return new Response\APIResponse($response);
480 | }
481 |
482 | /**
483 | * Get user info by profile URL or nickname
484 | *
485 | * @param string $query TikTok username
486 | *
487 | * @throws \TikTokRESTAPI\Exception\TikTokException
488 | * @throws \TikTokRESTAPI\Exception\BadRequestException
489 | * @throws \TikTokRESTAPI\Exception\ForbiddenException
490 | * @throws \TikTokRESTAPI\Exception\NotFoundException
491 | * @throws \TikTokRESTAPI\Exception\ProxyAuthException
492 | * @throws \TikTokRESTAPI\Exception\TooManyRequestsException
493 | * @throws \Exception
494 | *
495 | * @return \TikTokRESTAPI\Response\APIResponse
496 | */
497 | public function getUserInfo(
498 | $query = '')
499 | {
500 | if (empty($query)) {
501 | throw new TikTokException("Empty username.");
502 | }
503 |
504 | $response = $this->request('getUserInfo')
505 | ->addParam('license_key', $this->licenseKey)
506 | ->addParam('query', $query)
507 | ->getResponse();
508 |
509 | return new Response\APIResponse($response);
510 | }
511 |
512 | /**
513 | * Create a custom API request.
514 | *
515 | * Used internally, but can also be used by end-users if they want
516 | * to create completely custom API queries without modifying this library.
517 | *
518 | * @param string $endpoint
519 | *
520 | * @throws \TikTokRESTAPI\Exception\TikTokException
521 | * @throws \TikTokRESTAPI\Exception\BadRequestException
522 | * @throws \TikTokRESTAPI\Exception\ForbiddenException
523 | * @throws \TikTokRESTAPI\Exception\NotFoundException
524 | * @throws \TikTokRESTAPI\Exception\ProxyAuthException
525 | * @throws \TikTokRESTAPI\Exception\TooManyRequestsException
526 | * @throws \Exception
527 | *
528 | * @return \TikTokRESTAPI\Request
529 | */
530 | public function request(
531 | $endpoint = '')
532 | {
533 | return new Request($this, $endpoint);
534 | }
535 | }
--------------------------------------------------------------------------------