- The whole "Maximum cost per run" you set is now spent on trends. Before this build the run held back about a tenth of your cost cap before it started — a cushion for platform running costs which, on this actor's pricing, your cap does not pay for at all: your cap buys trends, and the running costs are ours. So the cushion was simply cap you had asked to spend and could not get. On a run capped at $0.10 with trends at $0.001 the plan asked for 90 trends where the cap paid for 100 — 10 trends of your own cap, unspendable by construction. From this build the plan uses your cap in full, so a run asks for as many trends as your cap can really pay for. Nothing you are charged changes, and nothing can be charged above the cap you typed: every charge is still checked against what is left of your cap at the moment it is posted, and a run that reaches your cap still stops cleanly, ships what it had already fetched, and tells you what is left. No price, input field or output column changes.
- The page now says what a second run of the same trend boards costs. It already told you the five sources do not move at the same speed and that a schedule pays the same per trend as a one-off run — but it never said the thing that decides a cadence: this actor keeps no memory of what it handed you, on purpose, because a remembered trend board would be a stale one. So a re-run inside a platform's own refresh window hands back the same board and charges for it again. The page says that plainly now, next to the cadence advice, and says the other half too: an early run is still only ever charged for the rows it handed you, because starting costs nothing and a platform that went quiet or does not carry your country comes back uncharged. Nothing you type, no output column, no charged event and no price moved.
- The keyword-volume fee this page mentions is live now, so the page states it plainly instead of announcing it. The shelf section told you that a run buying fresh volume data would begin adding a $0.19 fresh-lookup fee on a coming date. That fee took effect, so the sentence is now in the present tense: a run that buys fresh volume data adds one fresh-lookup fee of $0.19, and runs answered from the 30-day cache pay none. The shelf line naming the three actors that carry a small delivery-conditional fee reads the same way. This build changes nothing about this actor: no input field, output column, charged event or price of its own moved.
- The page now says, on its first screen, that the five sources do not move at the same speed — so you can pick a schedule before you spend anything. Google's is a daily search trends feed and TikTok publishes its hashtag boards as 7-, 30- and 90-day windows, so a daily run brings new Google rows long before a TikTok board has changed. Every row already carried
capturedAt, which tells you how fresh each platform's own answer was; the page now points at it where the decision is actually made, and repeats that nothing is charged for starting a run, so a schedule costs the same per trend as a one-off. Nothing about the run changed: no price, input field, output column or charged event moved.
-
The card now says what a TikTok row actually is. The listing leads on TikTok trends, and what TikTok publishes to a logged-out reader is its top hashtags — the top 3 for each of the 7-, 30- and 90-day windows, about nine rows; the rest of the list sits behind a TikTok login. This page and the input form have said so since the actor was listed, but the store card did not, so a buyer arriving on the TikTok phrase could expect a long TikTok feed. The card now names the scope before you spend anything. Nothing about the run changed: the same rows come back, from the same source, at the same price.
-
The card no longer implies every row carries a metric. It promised "rank, metric and link" on one row shape. A metric is whatever the platform itself publishes next to the trend, and some publish none — X does not publish a post count on its endpoint, and the YouTube trending chart a first run reads carries no view count either, so those rows come back with an empty metric and a metricReason saying which. The card now promises a metric where the platform publishes one, which is what the rows have always delivered. No price, input field, output column or charged event changed.
- The input form now opens on a first run that finishes in about a minute instead of one that pulls 250 trends. The form arrives with all five sources picked, and
Max trends per platform used to sit empty and fall back to 50 — so pressing Start on the example gave you up to 250 trends and about $1.00 on the Apify free plan before you had decided anything. The form now opens with that limit set to 5, so the example run returns up to 25 trends across all five sources for about $0.10 and comes back quickly. This is a starting value in the form only: the limit still falls back to 50 whenever it is left out by an API call, a scheduled task or an integration, so nothing you have already wired up changes. Nothing else moved: no input field, output column, event or price changed.
- The page now shows a full delivered row, not just a few columns of one. The Output section carried a screenshot and a trimmed table; it now also ends with a complete row from a live run — rank, metric, link, the news behind the trend and the charge record — so you can see the exact shape before you spend anything. No price, no input, no output column and no charged event changed.
- The input form now opens with the call that works, what one trend costs and what is never charged — the screen an AI agent reads. An AI agent shopping the store never reads this page: it reads the input form's own description, and that description used to open by telling a human to click Start. It now opens with a ready-to-send input naming all five sources and the country, says which field is required and that every other one can be left out or sent as null, gives the per-trend price and the per-1,000 arithmetic with the size of a full five-platform run, repeats that nothing is charged for starting a run, lists what is never charged — a platform that goes quiet, a country a platform does not carry, WORLDWIDE anywhere but X — names the run option that caps the bill and the two limits that bound the work, and points a timeline or a country trending-search question at the right sibling actor. Platforms leads with the value shape and its example, then what is never charged and where a neighbouring question belongs, before the per-platform notes; the console instruction now comes last. Nothing else moved: no input field, output column, event or price changed, and the console form behaves exactly as before.
- An aborted or migrated run now leaves its receipt from the first moment of the run, instead of only after start-up finishes. The record that says how a run ended was only put in place once the run had finished starting up — reading your input, opening its stores, working out what a previous attempt had already delivered and charged. A run stopped inside that window ended with nothing written about it at all, which mattered most on a re-started run, where the thing not written about was the earlier attempt's work. It is now in place from the run's first moment. Nothing else moved: no input field, output column, event or price changed, and a run that reaches its work behaves exactly as before.
- The links to our other scrapers on this page name them correctly again. Several of those actors were retitled on the store, and this page still used their old names. The links always pointed at the right actors; only the words were out of date.
- A limit outside this actor's range no longer refuses to start the run. "Max trends per platform", "Max trends for the whole run" and "Max run seconds" each had their range enforced by the input form itself, so
maxItems: 20000, or an AI agent guessing maxRunSeconds: 10, did not start a run at all: you got a validation error, no rows, no status line and nothing to look at. The ranges are unchanged — up to 250 trends from one platform, 5,000 for a run, and a run window between 30 seconds and an hour. What changed is what an ask outside one of them does: the run now starts, uses the nearest end of the range, writes one uncharged row saying what you asked for and what bound it, and names it on the run's status line. Your defaults and prefills are unchanged, the Platforms dropdown is untouched, and nothing about what a run costs moved.
- The FAQ now states what a no-input run actually delivers and what it actually costs. Clicking Start with
nothing filled in returns ten charged rows — the top 5 trends from Google and the top 5 from YouTube for the
US — plus one uncharged row naming the sample. The page used to answer "a cent or two", which understated the
sample on every plan; it now names the ten rows and puts the free-plan cost of the whole sample under five
cents, less on every paid plan. The sample itself is unchanged — same platforms, same five rows each, same
per-row price — only the sentence describing it was wrong.
- Nothing else moved: no input field, output column, event or price changed.
- This actor is now listed as "TikTok Trends Scraper — X, Pinterest, YouTube & Google Trends". It is the same actor at the same address, with the same input and the same five platforms — X, TikTok, Pinterest, YouTube Charts and Google. Only the name on the store page changed: the link you have saved, your saved tasks, your schedules and your integrations all keep working, and the rename adds no platform and changes nothing about what a run returns. The store description leads with TikTok now for the same reason, and every price and charging sentence in it is word for word what it was.
- The README opens with the one-click MCP pin instead of burying it at the bottom. The pin link, the actor id, the one input field you have to set with a real example, and how to cap what a run may spend now sit in the first screen, so an agent reading this page finds them.
- A maintenance note: nothing about your runs changes. The private run-report this actor writes for our own support — counts only, never anything you typed — now also records what one charged event cost on the run, beside the count of them. Only we read that record.
- Nothing you can see changed otherwise. Your rows, your columns, your receipt row, your status line and your bill are exactly as they were — only delivered trends are charged, and a row that was not delivered is not charged.
- Nothing you can see changed in this build. When a platform does not answer, this actor's own diagnostic record now keeps three cases apart that it used to file under one word: a platform temporarily refusing us (the case this actor waits out and asks again on), a platform that did not serve its trend list at that address at all, and a fault at our end. Only we read that record — your rows, your columns, every row status, your receipt row, your status line and your bill are exactly as they were, and only delivered trends are charged.
- Waiting out a temporary block is now sized by what the pending trends are actually worth, so a small ask no longer waits as long as a large one; a run that has returned nothing still gets one short retry.
- Nothing you can see changed otherwise. Your rows, your columns, your receipt row, your status line and your bill are exactly as they were — only delivered trends are charged, and a row that was not delivered is not charged.
- A platform that refuses can now be waited out on a normal-length run. When a platform refuses every connection, this actor pauses and asks again on fresh connections rather than giving up at the first refusal. On TikTok that could never actually happen: the run kept back more time for the second attempt than the default ten-minute run window holds, so the wait was always declined and the uncharged "please re-run" row shipped in seconds. TikTok now keeps back only what one look really costs, and a run at the default time limit waits and asks again like every other platform.
- A run's own clock can no longer cut a fetch off mid-look. A look that the remaining time cannot finish is not started at all, so the run always has room to write your rows and its summary. When the clock is what ended a platform's walk, the uncharged row says so and names Max run seconds, instead of reading like the platform refused you.
- An uncharged row no longer claims a cause the run did not measure. These rows used to open "rate-limited, blocked or dropped the request" whatever had actually happened — including when the fault was ours, such as this actor's own page service not answering. A row now says only what the run saw: the platform did not return its trend list, it is temporary, nothing was charged, please re-run. Where the cause really is known — our own service, our own page budget, your run's time limit — the row names it plainly.
- Short runs get a fairer share of their own clock. A run set near this actor's 30-second minimum kept a flat 15 seconds back for its closing report, leaving less time than a single fetch takes. The reserve is now a quarter of the window instead, and each fetch is given only as long as the run can actually afford. Runs of a minute or more are unchanged.
- Nothing you can see changed otherwise. Your rows, your columns, your receipt row, your status line and your bill are exactly as they were — only delivered trends are charged, and a row that was not delivered is not charged.
- "twitter" now selects X. The platform list takes
x, and this actor's own form labels that option "X (Twitter) trends" — but typing "twitter" was refused, so a platform you clearly named returned nothing. It now works, as do "twitter.com" and "x.com", and the other options' own labels ("Pinterest top search terms", "YouTube Charts (music)", "Google daily search trends", "TikTok top trending hashtags") along with each platform's own web address.
- A platform this actor does not read is still named back to you, never swapped for a neighbour. Douyin is a different app from TikTok with a different list of trends, and returning TikTok's hashtags to someone who asked for Douyin's would read exactly like the right answer. Anything this actor cannot read is still refused by name on one uncharged row, and the platforms it could read in the same list still run.
- Nothing else moved: no price, event, output column or charge changed, and only delivered results are charged.
- The run's own record now counts the trend rows your limits left uncollected. When your Max items cap filled, your maximum cost per run was reached, or the run's clock ended the walk, the platforms still ahead of it — and the rows a platform had already listed — were simply absent from the report this run writes back to us: a run that asked for a hundred rows and delivered seven closed its books with ninety-three named by nothing at all. Each is now counted under the limit that stopped it, so a run that stops short of what you asked for is visible to us without you having to report it.
- A run that stopped at your item cap now also records whether that cap really filled. It is one true-or-false fact about the run, never the number you typed, and it lets us see a run that claimed your cap stopped it while it had in fact delivered fewer rows than you allowed.
- Nothing you can see changed. Your rows, your columns, your receipt row and your bill are exactly as they were — only delivered rows are charged, and a row that was not delivered is not charged.
- The run's own account of what it asked for is now counted in trends, not platforms. Every run keeps a record of what was asked for, what was delivered and what came back with nothing. That record counted the ask as a number of PLATFORMS while counting the delivery in TRENDS, so a run that read a few platforms and delivered hundreds of trends never added up — and a platform that quietly answered with nothing could hide inside the mismatch instead of being named. The ask is now restated in trends as each platform answers: a platform that lists trends asks for the trends it listed, a platform that answered with nothing, refused, or was not read at all counts as one, and a row cap you set is reported as the stop it is rather than quietly shrinking the ask. What is delivered, what is charged and what the rows say are all unchanged.
- A country this actor cannot read is now counted against every platform you picked. That input mistake stops the whole run, because every platform is asked for the same country — it used to be recorded once however many platforms were planned, which under-counted what the run did not do.
- A platform the run's remaining budget could not pay to fetch is now counted as well as named. The uncharged row naming the setting is unchanged; it now also lands in the run's own record instead of leaving a gap in it.
- Charges are unchanged. Only delivered trends are charged; a platform that answered with nothing, refused, or was skipped is never charged.
- A run that waits now always keeps room to finish and report. When a platform refuses every connection, the run can pause and work that platform again — but the check that decided whether a pause was affordable kept back only half a minute for the tries after it, while a full set of tries on a platform takes about a minute and a half (and twice that on a platform that needs a date lookup first). On a short run — the five-minute limit the daily health check uses among them — a pause could be allowed and the tries after it then ran into the time the run keeps back for writing your rows and the end-of-run summary. Each platform now tells the check how long its own full set of tries takes, so a pause is only taken when the run can finish the work the pause was for. A run with room to wait waits exactly as it did before; a run without it answers straight away instead of running short.
- Charges are unchanged. Waiting is uncharged, a refused platform is uncharged, and only delivered trends are charged.
- A run you start with nothing set can now wait out a refusal too. Pressing Start on the untouched form runs a real sample — the top trends from Google and YouTube — and that sample had its own three-minute limit, which was too short to wait for anything. If a platform refused every connection, the sample ended it in about a minute and a half and shipped the uncharged "please re-run" row, while the pause that would have cleared it was still ahead. The sample's own limit is now nine minutes: enough for one platform's whole connection ladder, a pause of up to three minutes, that whole ladder again, and the second platform's own full ladder, with the time to write the honest row and the summary always kept back. A sample the platforms answer straight away is exactly as fast as it always was — the limit is a ceiling, never a wait — and a lower limit you set yourself still binds.
- "Max run seconds" now defaults to 600 instead of 300. By the same arithmetic, 300 seconds could never hold a pause either, so anyone who picked a platform and set no time limit was worse off than someone who picked none. A run answered at once is unchanged, and your own limit still binds when you set one.
- A platform with nothing queued behind it may now use the rest of the run's time to be patient. The waiting budget used to be a flat half of the time left, whatever you asked for. It is now sized to the ask: the last platform in your list has nothing waiting after it, so it may use what is left, while an earlier one keeps half back for the platforms still to come. No run is made less patient than it was.
- Charges are unchanged. Waiting is uncharged, a refused platform is uncharged, and only delivered trends are charged. A bare Start still delivers at most ten trends, still reads only the two direct-connection platforms, and never buys the paid rendered route.
- When a platform refuses every connection and the run still has time, it now waits and asks again. A throttle, a challenge or a server error used to end that platform in seconds: a couple of quick retries, then an uncharged "please re-run" row — while a run with a long time limit still had almost all of it left. The platform's whole connection ladder is now walked again after a pause, on fresh sessions, for as long as the run can afford it — never more than eight minutes of waiting in total, and never more than half the time the run had left when the first refusal came, with the time to write the honest row always kept back. When the platform names its own reset time ("try again in 30 seconds"), the run waits exactly that instead of guessing. A run with a short time limit still answers at once.
- A platform that answers with an empty list is now reported apart from one that refused. An answered-empty platform was counted together with a blocked one, so a quiet country read the same as an outage. It is now its own count on the run record and the summary row.
- The uncharged row on a platform the run waited for says so. Instead of handing back the platform's own "try again in about N minutes" — advice the run has now taken — the row says how long the run waited, over how many tries, and that the platform was still refusing. A row on a run that did not wait is unchanged.
- TikTok's rendered lane gets the same second look, and never at the cost of a partial one. The second walk is taken only while the run's page budget can still cover a whole one, so a run can never spend half a lane's worth of pages for nothing.
- A run near its time limit now stops cleanly instead of retrying past it. When a platform briefly refuses a request, this actor retries it a couple of times with a short pause. Those retries now watch the run's own clock, so a run at its time limit ends with the trends it has rather than being cut off part-way through a retry.
- Setting a country or a limit and picking no platforms now runs the sample under those settings, instead of returning nothing. Until now the Google + YouTube sample only ran when the form was completely untouched, so anyone who set their own market or a row cap and picked no platforms got one guidance row and no trends — a worse first run than clicking Start on the untouched form. Now the settings you chose are kept — the sample platforms are read for the market you picked — everything you did not set takes the sample's own value, and a per-platform, whole-run or run-seconds limit above the sample's own is treated as a ceiling rather than a request, so a sample can never grow into a bill you did not ask for. The trend rows are charged like any run; one extra
sample_note row names the settings that were kept and is never charged. An input field name this actor does not recognise, a platforms list filled with blanks, and a country the actor cannot read all still get the guidance row they had.
- A country code or a platform name we could not read is now reported back to us by the field it was in — "Country" or "Platforms", the field name only and never the value you typed. Input mistakes were reaching your rows but not our own run reports at all, so a check that is too strict looked like many unrelated typos instead of one thing to fix.
- A small run now gets the TikTok lane it is asking for. A run whose limits covered only a few trends could never reach the paid route TikTok needs, so it stopped at the limit with nothing to show. The first such route in a run is now always taken; every later one still has to be covered by what the run can still collect.
- A run that stops before it starts now reports its outcome too — a run refused for its memory setting now reaches us the same way every other run does: counts and reason codes only, never your input or your rows.
- Every run now reports its own outcome to us — counts and reason codes only, never your input or your rows — so a run that goes wrong reaches us even when nobody shares it.
- Run status lines fit the run page again; sample-run wording shortened.
A run that resumes after a platform restart now recognises every row it already delivered, so nothing is delivered or charged twice.
Apify occasionally moves a running actor to another server. When that happens, the run re-reads its own dataset to remember what it already delivered. Until now it trusted the dataset's row count, which can lag for a moment after a restart; a lagging count could make the run start over and charge again for rows you already had, stop before the end, or stop the run outright as a precaution. The run now checks for real rows instead of trusting the count, and reads to the end whatever the count says. Rows, prices, charges and the status line on a normal run are exactly as before.
- A run that filled the row cap you set is no longer treated as a run that went wrong, including the platforms that cap left unread. The Issues-tab line appears only when something actually did go wrong.
- A run that filled the row cap you set is no longer treated as a run that went wrong. The Issues-tab line now appears only when something actually did.
- A run that ends with a problem now says where to reach us. A miss, an input error, an early stop or a failed run closes by pointing at the Issues tab and naming the reply time; a fully delivered run is left alone.
- One support promise across this page — issues are answered in a couple of hours, always within a day.
Documentation build: nothing about what runs, what is delivered or what is charged changed.
- The screenshots on this page now load from Apify storage. The same two images of a real run, served from the platform itself instead of an outside host.
- Every link on this page now stays inside Apify. The free n8n workflow templates are unchanged and still free — the page now says they are listed on our profile website instead of linking out.
The suite blocks at the bottom of this page now state the three delivery-conditional fees that start 16 September 2026 on sibling actors — keyword volume's fresh lookup, profile posts' profile lookup, and Google Jobs' search fee. This page also now says "nothing charged for starting a run" wherever it used to say "no start fee" — the same promise, in the words the whole shelf uses. Nothing changes on this actor: same price, same events, same rows.
A run never spends more on a platform than it can bill.
- TikTok is collected only while the run can still pay for it. That platform is read through a rendered page per time window, which costs before it earns. When the rows the run can still charge for that platform would not cover those pages — a very small per-platform limit, or a cost cap that is nearly spent — the run skips the platform with an uncharged row that says so and names the setting to raise, and moves on to the next platform. Nothing changed about prices, about the rows you get, or about what is charged.
- Every other platform, and every run whose limits leave room, behaves exactly as before.
See the real thing before you run it.
- Two screenshots of an actual run now sit on this page: the input form exactly as it looks when you open the actor, and the dataset table it fills — Google daily search trends and YouTube trending chart rows side by side in one shape, with rank, metric and link.
- One link pins this actor in any AI agent (Claude, Cursor, or any MCP client) — it is at the bottom of the page.
- The input form's note about starting with nothing set now matches what that run does. It pulls the top 5 trends from Google and YouTube for the US, charged like any run; it stopped returning free placeholder rows in the previous build, and only the wording lagged behind.
- The links to the rest of the shelf carry each actor's current name.
Start with the default form and get real trends instead of placeholder rows.
- A bare Start now runs a two-platform sample. Click Start with nothing set (or send an empty input from the API) and the run pulls the top five trends from Google and YouTube for the US and returns their full rows, charged like any other rows. The five placeholder "sample rows" are gone; what you see is what a real run returns.
- The sample stays small and quick by design: two platforms, five rows each, and a three-minute window. On a bad minute you get uncharged rows saying a platform was not served (re-run in a minute), never an empty dataset.
- The status line says when a run was the sample and how to run your own platforms.
- Nothing else changed: any input with platforms in it behaves exactly as before, and a mistyped field still gets a row naming the field instead of a sample.
Sending null for a setting you do not want now means "use the default", instead of stopping the run before it starts.
- An optional setting sent as
null now takes its default. Agents, n8n templates and MCP callers routinely fill every field in a template and send null for the ones they have no value for. Until now Apify refused those runs before the container even started — you got a validation error, no run and no rows, and the fix was to know that you had to leave the key out entirely. Every optional setting on this actor now accepts null and reads it as "use the default", which is exactly what omitting it does. platforms is the one required setting and still needs a real value.
- Clearing the Country field takes the default too. An emptied country used to be reported back as an input mistake. It now means the United States, the same as leaving it alone.
- A country that is not real is unchanged — and still stops the run without charging you.
null and ZZ are opposite inputs and stay that way: null means "the default", while a two-letter code that is not a country still ends the run on an uncharged row that names the problem. Nothing is substituted and nothing is fetched, exactly as since 1.0.20.
- The input form and README no longer tell you to avoid
null. That instruction was true and is not any more.
TikTok now delivers on runs that used to come back with nothing.
- One time window that does not load no longer ends TikTok's run. TikTok publishes its top hashtags in three time windows — 7, 30 and 90 days — and this actor reads them in order. When the first window came back as a page that had not finished drawing itself, the run stopped right there and TikTok's row said the platform was temporarily unavailable — while the other two windows sat unread and might have loaded perfectly. The run now moves on to the next window before it reports anything, so a first window that stumbles costs you that window, not the whole platform. Two windows in a row that will not load still end it: uncharged, re-runnable, and the row says so, exactly as before.
- A second look at a window now waits longer for the page to finish drawing. The first look gives the page ten seconds to build itself; where that was not enough, the second gives it twenty. It costs nothing extra, and on a slow render it is the difference between a half-drawn page and real trends.
- A dropped connection is retried where it happens, instead of spending one of the window's two looks. A single blip used to leave a window with one real look at the page instead of two, and a run could report a platform unavailable on the strength of one connection that never completed. Connection trouble is now retried on its own, and every window still gets its two real looks. The run's own time limit still stops all of it cleanly, and no window is ever looked at more than three times.
- The Output tab now states exactly which rows are priced. It already named the
charged column; it now names the one row status that bills — status: ok, a delivered trend — and lists every status that carries no result fee.
- "Costs nothing" is now stated accurately. The input form and this page said a run with no platforms selected "costs nothing". There is no result fee on it — there is nothing to charge for — but Apify's own usage for the seconds that run lives is still yours, as on any run. The wording now says that instead.
A safeguard build. Nothing about what this actor delivers or charges today changed.
- The rows you are never charged for can never quietly become billable. The sample rows, the row that names an input mistake, the per-platform rows that explain why a platform returned nothing, and the run's summary row are all uncharged because this actor bills a named event per delivered trend — writing a row costs nothing by itself. That is not true of every billing setup: where a dataset row is itself the billed unit, the rows meant to cost you nothing would land on your bill. The run now reads its own billing setup before it writes anything, and on such a setup it reports those platforms, those input mistakes and the run's own totals in the run status line and in the run's record (Key-value store →
OUTPUT) instead of writing rows you would be charged for. On the current setup every one of those rows still ships exactly as before, in the same order.
- A delivered row states what it cost on any billing setup. The
charged column is settled from what the run actually billed — including a setup where a row is billed simply by being written, which such a row used to report as uncharged.
A country code this actor cannot read now stops the run instead of quietly running it somewhere else.
- A
country that is not a country code is answered and nothing else. A value like ZZ, UK or United States used to get an uncharged row naming the fix — and then the run went ahead and fetched United States trends anyway, and charged for them. It now ends on that row: no platform is contacted, no trend row is delivered, nothing is charged, and the run still finishes SUCCEEDED. This is what the "Countries" section and the "What you are never charged for" table on this page always said, and now it is true as written.
- The guidance row no longer says "This run used US". It names the code you typed, the code that works where there is an obvious one (
UK → GB), and states plainly that nothing was fetched.
- Real country codes are untouched: they are still trimmed, upper-cased and passed straight through, and which countries a platform actually carries is still that platform's own answer on its own uncharged row.
- The linked sample dataset is described as one verified run of the current code — the same dataset, unchanged.
This page now states the price up front. Nothing about what this actor delivers or charges changed.
- The price is on the page, not only in the store header. From $1.00/1,000 social trends — all-inclusive pay per event, no start fee, charged only on delivery — the same figure the store header and the Pricing tab already showed.
The linked sample dataset is re-shot from a run of the current build. Nothing about what this actor delivers or charges changed.
- The sample dataset now shows every column this page describes. The previous sample predated the per-row
placeReason and metricReason columns and covered four platforms; the new one is a single US run across all five — X, Pinterest, YouTube Charts, Google and TikTok — 49 trends, ending with the run's uncharged summary row, exactly as a paid run returns them.
Every column that can come back empty now says why it is empty, on the row itself.
place was blank on three of the five platforms with nothing to explain it. X names the place it served and TikTok's page names its region, so the column looked broken on Google, Pinterest and YouTube Charts rows rather than simply unpublished. Those three are asked for a country and answer with rows only — they never name a place — so their rows now carry a placeReason saying exactly that. country is still the geography on every row, and the column is never filled in with a label this actor made up.
- A missing number now names itself too. Where a platform publishes no figure for a chart — every X row, and YouTube's trending chart — the row carries a
metricReason beside the empty metricValue. The top-views charts, Google, Pinterest and TikTok publish real numbers and carry no reason at all.
- A view count that arrives empty can no longer be read as zero. An empty or missing view count from YouTube Charts is reported as unpublished. Before, an empty value could have been read as a real count of zero views on a charged row.
- The sample rows a
{} run returns now match what each platform really delivers. Three of the five samples showed a place their live rows never carry. They now show the same blank, with the same reason, that a real run gives you.
A platform whose trend list was not served is no longer reported as a platform that published nothing.
- A trend list that was not served this run now gets its own uncharged row, and it invites a re-run. When a platform's trend page could not be reached at all — the address did not answer, or the page was not there on this run — the row used to say the platform had answered normally and published no trends for that country. That is a verdict about the data, and the run had no grounds for it: it sent people away from a country whose trends were simply not served that time. Such a row now says the list was not served on this run, is marked re-runnable, and notes that a country where it keeps happening may no longer have a trend list on that platform. It is counted with the temporarily unavailable platforms in the run's status line, and nothing is charged for it.
- The "published nothing" row is now reserved for a platform that actually answered. A platform still gets it only when its own page came back and carried no trends.
Clearer release notes — this page's notes now read more plainly. Nothing about what this actor delivers or charges changed.
Suite links now point at the full live shelf — every actor named in this README is a live
store link. Nothing about what this actor delivers or charges changed.
Review-fix build: honest counting at the run's edges.
- A resumed run counts only trends as delivered. The uncharged note written when a platform's walk cut itself short was being counted as a delivered trend when a moved or resurrected run added up its progress — such a run could stop short of your
maxItems and report more delivered than it was. Notes of every kind are now excluded from that count; only real trend rows are.
- A resumed run that cannot trust its own delivery record now stops rather than charging again. Right after a run is moved or resurrected, the dataset read-back can momentarily lag behind what has already been charged. A run that trusted such a read would start the work over — fetching, delivering and charging a second time for trends you had already paid for. It now notices that its charges exceed what the record shows, stops cleanly without charging anything more, and says so. Re-running once the record has settled carries on normally.
- One more kind of account-side refusal on the TikTok arm now stops that walk at once. It is trouble on our side, exactly like the account-side refusals handled before it — retrying could never help. The walk now stops immediately with one uncharged row saying the request did not get through, and the other four platforms are untouched.
- The memory range the run form offers now matches what a run accepts. The form offered settings up to 4096 MB while the actor accepts at most 2048 MB, so picking a value above that bought an immediate, uncharged refusal. The form's range now ends where the actor's does.
- An empty numeric setting now means "use the default". Sending
null or an empty string for a numeric option — as templated API callers often do — used to be read as zero and clamped up to the smallest allowed value. It is now treated as not set and gets the documented default.
When the trouble is on our side of the TikTok arm, the run now stops at once and says so, instead of retrying advice that could never help.
- An account-side refusal on the TikTok arm now stops the walk immediately. It used to be retried on every time window as if it were temporary weather, and the run's answer was "please re-run" — advice that could never work, because the refusal is on our side, not yours. It now gets the same clean stop other refusals of this kind already had: no retries, one uncharged row saying the request did not get through, and the other four platforms untouched.
- The TikTok arm's own spending guard now counts exactly. An answer that came back blank, zero or oddly shaped could move that internal meter by the wrong amount, letting the guard stop the walk too early or too late. The meter protects our spend, not yours — nothing about what you are charged has changed.
- README: the trends & keyword suite links and the full steadyfetch shelf now point at the published actors.
A platform that refused, stalled or answered with something unreadable is now reported as something to re-run, never as a platform with no trends.
- A refusal or a challenge page is no longer reported as "this platform published nothing". When a platform answered with a rate-limit notice, a challenge, or any response that was not its trends list, the run used to say the platform had answered normally and published no trends for that country — permanent wording for a temporary problem. Every platform is now checked for its own answer before that can be said. Anything else returns one uncharged row saying the request did not get through and asking you to re-run. A platform that genuinely published nothing still gets the honest empty row it always did, and nothing about what gets charged has changed.
- A Pinterest run that could not read which week of trends is ready now says so. That lookup runs before the trends themselves; when it failed, the whole Pinterest arm came back as "Pinterest published no trends for this country". It now returns one uncharged, re-runnable row naming what did not happen. No extra requests are spent on it.
A typo in an input field name now gets a helpful pointer instead of sample rows.
- A misspelled field name is answered with the field you meant. Sending your platform list
under a name this actor does not have —
sources instead of platforms, say — or filling in
only the country and the limits, used to come back as the uncharged sample rows. Those samples
are all stamped US, so a run that asked for another country and misspelled the platform field
read like a real answer for the wrong one. Such a run now returns one uncharged row that names
the field the actor did not recognise, names the one it does, and shows the shape to send. Runs
that do name platforms are unchanged, and a run with nothing set at all still returns the
sample rows.
TikTok trending hashtags join the four existing platforms — same pricing, same honest rows.
- TikTok is a platform option again. Each run returns the top trending hashtags TikTok
shows publicly for your country — the top 3 for each of its 7-, 30- and 90-day windows,
about 9 rows per run — with posts, views, category and a link, in the same row shape as
the other platforms. TikTok keeps the rest of its list behind a login; this actor delivers
exactly what the public page shows and does not pretend otherwise.
- TikTok covers a fixed list of 27 countries (see the README). A country outside it, or
WORLDWIDE, comes back as an uncharged row naming the fix — before anything is fetched.
- Same pricing, same rules as every other platform: one
social-trend event per delivered
row, and a TikTok page that is blocked, empty or unreadable ships one uncharged row
saying so. The other platforms are never affected by TikTok's weather.
- A TikTok walk cut short by this actor's own page budget now says so. It used to finish
as "Completed" with fewer rows than the page holds and no explanation. The run log now names
the early stop, and one uncharged row says what happened and that a re-run collects the
remaining time windows.
- An account-side refusal on the TikTok arm stops the walk immediately instead of being
retried as if it were temporary weather. Nothing is charged for it.
- Maintenance alarms got sharper: a TikTok page-layout change that breaks some time windows
while others still deliver — or a page that renders but yields nothing readable — is now
flagged to us on every run. Your delivered rows and charges are unchanged either way.
- Sample runs (no platforms selected) now return five example rows, one per platform.
- A restarted run's status line now counts the whole run, not just the final stretch. A
resumed run could say "Delivered 4 trends from 0 of 2 platforms" — the trends were real,
delivered before the restart, but the platform counts only covered the part after it. The
whole sentence now reflects everything the run delivered. The summary row was always
correct and is unchanged.
A country code that can never work is now said to be wrong, instead of being blamed on the platform.
- A two-letter code that is not a country — a typo such as
ZZ — is answered before
anything is fetched. It used to be sent to the platforms, come back refused, and be
reported as a temporary block you should "please re-run" — advice that could never work,
however many times you ran it. You now get one uncharged row that names the mistake, and
the run continues on US, the same answer any country we could not read already gave.
- Codes people type that are not country codes now name the one that works —
UK
points at GB, for example.
- Which countries a platform actually carries is unchanged: that is still the platform's
answer, and it still comes back as its own uncharged row naming the fix.
Interrupted runs no longer repeat themselves.
- A run that restarts mid-way never delivers or charges the same trend twice. Apify
moves long runs between servers, and clicking Resurrect restarts a finished run —
both used to start the collection over from the top, so the same trend could land in your
dataset twice and be charged twice. Each run now recognises what it has already delivered
and picks up from there: no duplicate rows, no duplicate charges, and a resumed run's
output is indistinguishable from one that ran straight through.
maxItems is a limit on the run, not on each restart. A restarted run used to be able
to deliver up to twice the cap you set. It now stops exactly where you set it.
maxRunSeconds and the actor's own time ceiling count the whole run, not the time
since the last restart.
- If a restarted run cannot re-read what it already delivered, it charges nothing at all
for that run rather than risk charging you twice, and the run status says so plainly.
- A platform the run never reached — because it stopped at your row cap, cost cap or
time limit — is now reported as exactly that. It used to be lumped in with "published
nothing for this country", which sent you to change a country that was never asked.
- Every row now carries a hidden delivery key so the above is possible. It is invisible in
the Output tab, in exports and in the API, and no visible column changed.
Initial release.
- Four trend sources in one run — X (Twitter), Pinterest, YouTube Charts and
Google — normalised to one row shape with
platform, chart, rank, title,
kind, metricName, metricValue, url and capturedAt, so the platforms stack into
a single table.
- Every row carries
charged and missReason: the invoice reconciles from the dataset
itself, and only rows with charged: true were billed.
- A platform that rate-limits, blocks or publishes nothing ships one uncharged row saying
which of those happened, and the run still succeeds. The other platforms are unaffected.
- Charging is gated on rows that actually parsed — never on the HTTP status line — so a
response that arrives empty or carries an error inside the body is never billed.
country accepts a two-letter code (WORLDWIDE on X only — the one platform that keeps
a real worldwide list). A country a platform does not carry comes back as an uncharged row
naming the fix — and the run summary says "does not cover this country" rather than
"published nothing", so you change the country instead of waiting for data that will
never arrive.
- Pinterest is asked for the latest date it actually holds before a window is requested, so
the run returns the freshest data that exists instead of an empty one.
- YouTube means YouTube Charts — trending music videos and artists — and every row says
which chart it came from.
- If a platform rate-limits or drops the first attempt, the run tries again over a different
network path before giving up, and the uncharged row says when it is worth retrying.
limitPerPlatform, maxItems and maxRunSeconds are hard limits: the run stops cleanly,
finishes successfully, and the summary row names which limit bound plus what was left.
- Running with no platforms selected returns four uncharged sample rows, one per platform,
without contacting anything.