Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG?] Error in video extraction: status code 10201 #58

Open
JailSeed opened this issue Jul 18, 2023 · 10 comments
Open

[BUG?] Error in video extraction: status code 10201 #58

JailSeed opened this issue Jul 18, 2023 · 10 comments
Labels
bug Something isn't working

Comments

@JailSeed
Copy link

Describe the bug
Hello! I tried the code provided as an example in the documentation under "Download Videos and Slideshows" section to download slideshows, but I get the 10201 error on any link.

To Reproduce
Steps to reproduce the behavior:

  1. Run the code from the documentation

Expected behavior
Slideshows can be downloaded

Version Information
pydantic==2.0.3
pydantic_core==2.3.0
playwright==1.36.0
tiktokapipy==0.2.1

System Information
Same behavior both on PC (Windows 11 22H2 , Python 3.11.4) and VPS (Ubuntu Server 22.04 LTS, Python 3.10.6)

Region Information
PC - Belarus
VPS - Germany

Additional context
Example links:
https://vm.tiktok.com/ZM2CEJ7Ba/
https://vm.tiktok.com/ZM2C51TKA/
https://vm.tiktok.com/ZM2CyJnWL/

Traceback (most recent call last):
  File "/home/srv1/tiktok.py", line 79, in <module>
    asyncio.run(download_video())
  File "/usr/lib/python3.10/asyncio/runners.py", line 44, in run
    return loop.run_until_complete(main)
  File "/usr/lib/python3.10/asyncio/base_events.py", line 646, in run_until_complete
    return future.result()
  File "/home/srv1/tiktok.py", line 71, in download_video
    video: Video = await api.video(link)
  File "/home/srv1/.local/lib/python3.10/site-packages/tiktokapipy/async_api.py", line 166, in video
    return self._extract_video_from_response(response)
  File "/home/srv1/.local/lib/python3.10/site-packages/tiktokapipy/api.py", line 297, in _extract_video_from_response
    raise TikTokAPIError(
tiktokapipy.TikTokAPIError: Error in video extraction: status code 10201 (Unknown Error)
@JailSeed JailSeed added the bug Something isn't working label Jul 18, 2023
@Russell-Newton
Copy link
Owner

Does the code work on any video that isn't a slideshow?

@JailSeed
Copy link
Author

Nope, the same error

@Russell-Newton
Copy link
Owner

That's interesting. I'm not getting this error on my end, which leads me to believe it's a region specific thing. If you try to access TikTok on your PC without being logged in, does it try to force you to login?

TikTok has been changing their privacy regulations to match EU restrictions, and I know part of that is that TikTok requires EU users to login. Although Belarus is not a member of the EU, I know there's some trade relations there with the EU, so there's likely similar privacy policies. It's also likely that TikTok might just be implementing the new restrictions across the whole EU. In either case, I'd be interested to see TikTok's standard behavior on your PC.

@JailSeed
Copy link
Author

Yeah, you are right. If I open a link in a browser without being logged in, a page opens and a video/slideshow starts playing, but immediately an authorization window pops up and then another one with captcha. Is there any way out of this situation without using a US VPN? For example, using browser cookies to bypass it like youtube-dl does.

@Russell-Newton
Copy link
Owner

I haven't yet been able to figure out exactly what the right combination of cookies, headers, and paramstring parameters is in order to get around this. Interestingly, there's a difference in behavior in Europe between video pages and user pages (I confirmed that youtube-dl also has this issue with user pages). On a user page, you can't even see any of their videos or other information. It just takes you straight to a login page, as seen in #47. At least getting to see the video/slideshow before the login prompt pops up leads me to believe making those API requests are possible.

The tricky part of this whole thing is that TikTok puts various signatures and checksums in the paramstrings of their API requests, and these are generated on the fly and are not always based on cookies. I'll keep looking into this.

@JailSeed
Copy link
Author

Got it, thanks. If any more information is needed on my end, I will be happy to help.

Russell-Newton added a commit that referenced this issue Jul 25, 2023
* #58, #61 - Resolved status code 10201 appearing when extracting videos from mobile app share links
* #59 - Suppressed two errors during user video iteration:
    * TypeError: `DeferredItemListIterator` no longer attempts to iterate over a None item_list
    * JSONDecodeError: `DeferredItemListIterator` cuts iteration short if an API request returns null JSON
@Russell-Newton
Copy link
Owner

This error should (hopefully) be fixed in version 0.2.2. It seems that the issue was actually related to a change I made to video extraction in 0.2.0. It looked for the video ID in the video URL, which is possible with a desktop URL, but the mobile app share links are shortened and don't contain that information.

@JailSeed
Copy link
Author

Thank you! This update definitely fixed this error, but the save_slideshow() method raises 403 Forbidden error, so I have rewriten the code from the documentation to use aiohttp with specified cookies in both save_video() and save_slideshow() methods:

from tiktokapipy.async_api import AsyncTikTokAPI
from tiktokapipy.models.video import Video
import aiohttp
import asyncio
import glob
import io
import logging
import os

link = ''
directory = ''


async def save_file(api: AsyncTikTokAPI, url: str, filename: str):
    async with aiohttp.ClientSession(cookies={cookie["name"]: cookie["value"] for cookie in await api.context.cookies() if cookie["name"] == "tt_chain_token"}) as session:
        async with session.get(url, headers={"referer": "https://www.tiktok.com/"}) as resp:
            downloaded = io.BytesIO(await resp.read())
            with open(os.path.join(directory, filename), "wb") as file:
                file.write(downloaded.getbuffer())


async def save_slideshow(video: Video, api: AsyncTikTokAPI):
    vf = "\"scale=iw*min(1080/iw\,1920/ih):ih*min(1080/iw\,1920/ih)," \
         "pad=1080:1920:(1080-iw)/2:(1920-ih)/2," \
         "format=yuv420p\""

    for i, image_data in enumerate(video.image_post.images):
        url = image_data.image_url.url_list[-1]
        await save_file(api, url, f"temp_{video.id}_{i:02}.jpg")

    await save_file(api, video.music.play_url, f"temp_{video.id}.mp3")

    command = [
        "ffmpeg",
        "-r 2/5",
        f"-i {directory}/temp_{video.id}_%02d.jpg",
        f"-i {directory}/temp_{video.id}.mp3",
        "-r 30",
        f"-vf {vf}",
        "-acodec copy",
        f"-t {len(video.image_post.images) * 2.5}",
        f"{directory}/temp_{video.id}.mp4",
        "-y"
    ]
    ffmpeg_proc = await asyncio.create_subprocess_shell(
        " ".join(command),
        stdout=asyncio.subprocess.PIPE,
        stderr=asyncio.subprocess.PIPE,
    )
    _, stderr = await ffmpeg_proc.communicate()
    generated_files = glob.glob(os.path.join(directory, f"temp_{video.id}*"))

    if not os.path.exists(os.path.join(directory, f"temp_{video.id}.mp4")):
        logging.error(stderr.decode("utf-8"))
        for file in generated_files:
            os.remove(file)
        raise Exception("Something went wrong with piecing the slideshow together")


async def save_video(video: Video, api: AsyncTikTokAPI):
    await save_file(api, video.video.download_addr, f"temp_{video.id}.mp4")


async def download_video():
    async with AsyncTikTokAPI() as api:
        video: Video = await api.video(link)
        if video.image_post:
            await save_slideshow(video, api)
        else:
            await save_video(video, api)


asyncio.run(download_video())

With this code I can download any slideshow from any link (PC/Mobile), but a video can be downloaded only from a PC link. A mobile link returns:

<HTML><HEAD>
<TITLE>Access Denied</TITLE>
</HEAD><BODY>
<H1>Access Denied</H1>
 
You don't have permission to access "http&#58;&#47;&#47;v16&#45;webapp&#45;prime&#46;tiktok&#46;com&#47;video&#47;tos&#47;alisg&#47;tos&#45;alisg&#45;pve&#45;0037c001&#47;oYcRuQozyAyAADVfhC5uvAIlCAVVNSdwtIEUu3&#47;&#63;" on this server.<P>
Reference&#32;&#35;18&#46;ece3617&#46;1690316430&#46;132b158c
</BODY>
</HTML>

@Russell-Newton
Copy link
Owner

This is a known issue that I'm working on. See #44.

@Russell-Newton
Copy link
Owner

This may be fixed in version 0.2.4 with the video download function. It doesn't work on slideshows and requires the optional yt-dlp dependency. This can be installed with pip install yt-dlp or pip install tiktokapipy[download]. It may not work 100% depending on where you are, but it works well for me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants