Every entry here is one build on the Builds tab, 1:1, newest first. Prune convention one.
- A run whose token can read your account memory but not write to it now says so, instead of quietly charging you for the same listings again next time. The memory that stops you paying twice lives in a key-value store in your own Apify account, and a scoped API token can be allowed to READ it and not to write it — or to write it but not to create it. Such a run looked perfect: it skipped the listings you already had, delivered the new ones, and recorded none of them, so your very next run collected and charged for that whole delivery all over again. This actor keeps a separate memory for each search, so a token without Create permission met that wall on every new search, not just the first time you used it. The run now says it on the run page, in the run log and on one uncharged row in the dataset, each naming exactly what to grant (key-value store Write, and Create, under Settings → API & Integrations) or the alternative of setting Actor runs to Full access. Runs on a full-access token are unchanged. No price, input field, output column or charged event changed.
- A re-started run no longer collects past the number of listings you asked for. Apify sometimes moves a run to another server part-way through; the run picks up where it left off. To know how many listings it had already handed you, it was counting the ones it had CHARGED for — and a listing can be delivered without being charged, on a run that bills nothing or once your maximum cost per run is reached. So it read its own tally low and kept collecting past your "Max listings" limit. It now counts the rows you actually have, and the optional details rows are not mistaken for listings in that count. If your run is never moved, nothing changes: this only ever showed up after a restart.
- A run started with a limited API token now tells you the repeat check could not run — before it charges you for listings you already had. The memory that stops you paying twice for the same listing lives in a key-value store in your own Apify account. A run started through the API with a token whose permissions are restricted cannot open it, so every listing you already had was collected and charged again, and nothing said so. That run now says it on the run page, in the run log, and on one uncharged row at the top of the dataset — each naming the permission to grant (key-value store Read, Write and Create, under Settings → API & Integrations) or the alternative, running it from the console. Runs from the console, and API runs on a full-access token, are unchanged: the check runs as before and a listing you already have is still never charged twice. No price, input field, output column or charged event changed.
- Nothing else moved: no input field, output column, charged event or price changed.
Austin, TX now works. A two-letter US state is spelled out (Austin, Texas) before the city
is looked up, so the shape most buyers type is placed on the first try and costs one lookup, not
two. If the spelled-out form finds nothing, your own spelling is tried once more, and a city that
still cannot be placed leaves one uncharged row naming both forms that were tried.
- Fixed: searches returned nothing at all. Four of the sort orders, and the
local_pick_up
delivery method, were sent to the search in this actor's own words rather than the ones the search
accepts — so every search, including the default one, failed and delivered no listings. The words
you type in the console are unchanged; they are now translated on the way out, and pinned against
the source's own answers so they cannot drift again.
- The run receipt says "2 cities", not "2 citys".
First public build.
- A city and a keyword return that city's Facebook Marketplace listings as rows: the listing ID and
its link, the title, the price as a number and as Facebook writes it, any strikethrough price, when
it was listed, the city and state, one photo, the category ID, mileage on a vehicle listing, the
delivery types, and whether the listing is sold, pending or still live.
- A city is a name or a coordinate pair.
Austin, Texas is placed for you; a bare "30.27,-97.74"
pair skips the lookup entirely. A name that cannot be placed leaves one uncharged row naming the
city, and maxUnresolvableCities (default 3) caps how many the run will try before it stops.
- You are never charged twice for a listing you already have. Every run remembers the listing IDs
it delivered to your account, and a later run skips them before anything is reserved or bought — so
the slot goes to the next new listing and you still get the number you asked for. Turn
skipListingsAlreadyDelivered off, or give a job its own memoryKey, to collect the same listings
again and watch a price.
maxListings is exact and counts across the whole run, not per city. It also answers to
maxItems, limit and maxResults, with the smallest one present binding and one uncharged note
row saying which name was read. Over 5000 is clamped in code and the clamp is never charged.
query, radiusKm, minPrice / maxPrice, condition, daysSinceListed, deliveryMethod,
sortBy and availability all narrow the search at the source. No filter fee — a band, a
radius or a date window is part of the row's price.
includeListingDetails adds one listingDetails row per listing: the seller's full description,
every photo, the attributes, the real currency code, the listing's own latitude and longitude, and
the shipping, Buy Now and messaging flags. Off by default, charged per details row delivered.
currency is an explicit null on every listing row, and so is description. Neither is in
the search feed a logged-out reader is served; both are real on a listingDetails row. This actor
does not promise a column it cannot fill.
- No seller is returned, on either row type — not a name, not an ID, not a profile link. A
Marketplace seller is a member of the public.
- Never charged: a city name that could not be placed, a search that returned nothing, a listing that
was gone by the time its details were read, a read that failed on our side, listings your own
filters or limits dropped, listings your account already had, and starting a run.
- A bound of this actor's own is labelled as ours:
skipped.page_cap when the feed was still
serving and the run had read the 40 pages it buys for one city, and skipped.all_repeat when a
page added no new listing. Neither is written as a verdict about the city.
- A cost cap ends the collecting, never the delivering: rows already in hand ship in full, and the
last row of the run says what stopped it and what is left.
- Pressing Start with no input returns the built-in sample rows and one uncharged note naming the two
fields that make a real run. Nothing is collected from Facebook and there is no result fee.