TikTok Video Uploader Pro - Auto-Post Videos
Pricing
from $550.00 / 1,000 video uploadeds
TikTok Video Uploader Pro - Auto-Post Videos
Post a video to TikTok from any public video URL: caption, privacy, confirmation and a link back. The upload fee is charged only on a confirmed post; the bytes a run really moves are billed per megabyte on any outcome, a failure included. Your own proxy is never billed per MB.
Pricing
from $550.00 / 1,000 video uploadeds
Rating
0.0
(0)
Developer
Dami's Studio
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
3 days ago
Last modified
Categories
Share
TikTok Video Uploader
Posts a video to your own TikTok account from a URL. You give it the video, a caption, and your own exported session cookies, and it drives a headless browser through TikTok's Studio upload page to publish the post. It's meant to be the publish step of a faceless-content or scheduling pipeline.
Best-effort browser automation. There is no official TikTok posting API for this, so the actor automates the real TikTok Studio web UI with your session cookies. TikTok actively detects automation and may show a captcha / "verify it's you" wall, or rate-limit / restrict / ban the account. Run it only on your own account, at your own discretion. When TikTok throws a wall the actor stops with a clear error and a debug screenshot — it does not silently hang.
How it works
It downloads your video, launches a headless Chromium routed through a residential proxy, loads your exported TikTok cookies into the session, opens the TikTok Studio upload page, sets the file, fills the caption, picks (and verifies) the privacy, clicks Post, and waits for TikTok's real "uploaded / published" confirmation before reporting success. There is no shared login — you bring your own session each run.
Try it with no login (demo mode)
Run it with no cookies (or set demoMode: true) and it returns one clearly-labeled SAMPLE row and uploads nothing. Use this to see the output shape before wiring up your session.
Input
| Field | Required | Notes |
|---|---|---|
videoUrl | for real uploads | Public direct, non-expired URL to the .mp4. You host it (S3, CDN, key-value store). |
cookies | for real uploads | Your TikTok session, exported as Cookie-Editor JSON. Leave blank for a demo run. Stored as a secret. |
caption | no | The caption. Put your #hashtags here. |
privacy | no | public, friends, or private. If private/friends can't be confirmed, the actor refuses to post (so it never publishes Public by accident). |
proxyConfiguration | no | By default the upload session goes out over this actor's own residential exit, and that exit is what the per-megabyte charge pays for (see Pricing). Set the country to match the account your cookies came from — a mismatch triggers captcha walls. Three things take the upload off that exit and switch the per-megabyte charge off with it entirely, on success and on failure alike: your own servers in proxyUrls (used exactly as given), selecting a non-residential proxy group, or unticking "Use Apify Proxy". TikTok is far likelier to show a captcha on a datacenter or direct connection, so that saving is a real trade-off, not free. |
demoMode | no | Force a no-upload sample run even with cookies. |
How to export your TikTok cookies
- Log into tiktok.com in Chrome/Edge as the account you want to post from.
- Install the Cookie-Editor extension and open it on a tiktok.com tab.
- Click Export → Export as JSON (this copies the whole cookie set to your clipboard).
- Paste that JSON into the
cookiesfield.
The export must include sessionid (and ideally sid_tt, tt_csrf_token, msToken) for .tiktok.com — sessionid alone is often not enough. Export from the same country your proxy uses. Cookies expire; re-export when you see a "not logged in" error.
Output
One dataset record. On a confirmed upload: { ok: true, platform, videoUrl, videoId, caption, privacy, privacyApplied, postedAt, runId }, where videoUrl/videoId point at the published post (resolved from the content manager; may be null if TikTok didn't surface it). On failure: { ok: false, error }, plus a bytesMoved block giving the exact byte counts this run moved and whether they crossed the metered connection, a chargeStatus, and a debug screenshot + page HTML in the run's key-value store. Every run also writes CHARGE_SUMMARY.json to that store with the settled billing figures. Demo runs carry _demo: true and a _notice.
Example
{"videoUrl": "https://cdn.example.com/clip.mp4","caption": "new drop today #fyp","privacy": "public","cookies": "[{\"name\":\"sessionid\",\"value\":\"...\",\"domain\":\".tiktok.com\",\"path\":\"/\"}]"}
Pricing
Three charges, no volume tiers and no plan gates:
| Charge | Amount | When it applies |
|---|---|---|
| Run start | $0.015 per event | Every run. The platform bills one start event per gigabyte of run memory, and this actor is fixed at 2 GB, so a run start costs $0.03. |
tiktok-upload | $0.55 | Once per run, and only after TikTok returns its real published confirmation. A run that publishes nothing never pays this. |
video-megabyte | $0.02 per MB | The megabytes the run actually moved over this actor's own metered residential connection, rounded up. Charged on every outcome, including runs that fail. Never charged at all on your own proxy, a non-residential group, or no proxy. |
Bandwidth is charged even when the post does not land
This is the one thing to read before you run it, because it changed on 25 August 2026.
The upload fee is still a success fee: if nothing is published, you are not billed for publishing. The per-megabyte line is different, and it is not really a fee — it is the cost of moving your video. TikTok checkpoints datacenter addresses on the upload flow, so this actor uploads through a residential connection it rents by the gigabyte. Those gigabytes are bought the moment they are used and cannot be handed back. A run that pulls your 30 MB file in and pushes it at TikTok has spent that bandwidth whether TikTok then confirms the post, throws a captcha, or changes its composer.
So the per-megabyte charge bills the megabytes the run really moved, measured as they move, on whatever outcome it reaches:
- your cookies turn out to be dead, or TikTok shows a "verify it's you" wall;
- TikTok refuses the post, or its composer changed shape underneath the automation;
- Post was clicked and TikTok never confirmed it;
- the run hit its own time limit (an abort is different — see below);
- the download broke part-way, or the file turned out to be over the size ceiling once the transfer was already running.
Two things it does not do. It never bills bytes that did not move — a run refused before the first byte costs nothing but the platform start fee, and a byte is counted where it crosses the wire, so an origin that compresses your file is billed for what it actually sent, not for the file's unpacked size. And it never bills more than the same run would have cost had it published: the ceiling is your file's own megabytes plus what the $0.55 upload fee would have covered, so a failed run always comes out cheaper than the successful version of itself — retries of a broken download included.
Every run writes the numbers down. The result row carries a bytesMoved block with the exact byte counts, and CHARGE_SUMMARY.json in the run's key-value store carries the settled figures taken from the platform's own answer — including how many megabytes were charged and how many the actor absorbed, if your maxTotalChargeUsd stopped the charge short.
Two honest limits, both measured rather than assumed. An aborted run is not charged for its bandwidth. The actor does listen for the abort, but when this was tested on 25 August 2026 the platform ended the run 212 milliseconds after announcing it — not the 30 seconds it advertises — which is not enough time to write a row or raise a charge. The same goes for a run the platform kills outright on its own timeout, and for a server migration. And if the actor cannot write you a result row at all, it charges nothing: no receipt, no bill.
What a run costs
| Run | Over this actor's residential exit | Over your own proxy, a non-residential group, or no proxy |
|---|---|---|
| 30 MB video, published | $0.03 + $0.55 + $0.60 = $1.18 | $0.03 + $0.55 = $0.58 |
| 300 MB video, published | $0.03 + $0.55 + $6.00 = $6.58 | $0.03 + $0.55 = $0.58 |
| 30 MB video, dead cookies — file downloaded, session opened | $0.03 + about $0.74 of bandwidth | $0.03 |
| Refused before anything moved (budget, bad input, bad cookie format) | $0.03 | $0.03 |
| Demo / sample run | $0.03 | $0.03 |
That failure figure is an example, not a fixed price: it is 30 MB of video plus roughly 7 MB of TikTok Studio. Your own run's exact number is in its row, split into the two legs. Worth knowing which is which: your file is pulled straight from videoUrl, not through the residential connection, so on a run that fails before the file reaches TikTok those megabytes are billed as bytes the run moved rather than as residential bandwidth. Only the TikTok Studio traffic in that example crossed the metered connection.
When the per-megabyte line is zero
video-megabyte pays for a metered connection, not for the file, so it is not charged at all — success or failure — when the bytes did not go over that connection. That is the case whenever you:
- put your own servers in
proxyConfiguration.proxyUrls— you already paid for that bandwidth once; - select a proxy group other than residential, so the run goes out over rotating datacenter addresses; or
- untick "Use Apify Proxy" and connect directly.
In all three the run pays the $0.03 start fee, plus the $0.55 upload fee if it publishes, and nothing more — whatever the video weighs and however the run ends. The run log states which exit was used and says explicitly when no per-megabyte charge was made. The trade-off is real: TikTok checkpoints datacenter and bare container addresses on the upload flow, so those runs hit captcha walls far more often.
Why the per-megabyte charge exists
An upload session needs a residential exit — TikTok walls the cheap ones — and residential bandwidth is billed by the gigabyte. Part of that traffic is fixed: booting Studio and driving the composer moves tens of megabytes whatever you post, and on a confirmed post the flat $0.55 covers it. The video's own bytes are the part that scales, and a flat fee alone stops covering them right around the median clip size. Billing those megabytes is what lets a large file go through and simply cost more, instead of being refused for being large.
Size limits and your own budget
A video above 500 MB is refused, on any connection. On the residential exit only, if you set maxTotalChargeUsd on the run, the actor checks before downloading that the budget still covers the megabytes it is about to bill; if it does not, the run stops with CHARGE_BUDGET_EXCEEDED before moving a byte, and charges nothing. That check does not exist on a connection of your own, because nothing there is billed by the megabyte.
maxTotalChargeUsd is honoured on the failure path too: the actor asks the platform how much of your budget is still available and charges no more than that, and CHARGE_SUMMARY.json says plainly when your cap stopped the charge short and how many megabytes the actor absorbed as a result.
Notes
This automates your logged-in TikTok session, which TikTok's terms discourage — see the warning at the top. Because it drives TikTok's actual web UI, a layout change on their side can break a selector and need an update; when that happens the actor fails with an actionable message and saves a screenshot rather than reporting a false success.

