28 September – 4 October 2026
What changed that week, dated, in the order it happened.
The OpenAPI spec covers every path, and MCP refuses what it cannot use
Improved
- The spec now has `GET /v1/account`, `/v1/usage`, `/v1/endpoints`, `/v1/errors` and `/v1/status`, and every status the job paths return. A client generated from it can read its balance.
- An endpoint or a parameter that is not live yet is marked `x-available: false` or left out, so a generated client does not call it.
- Patterns in the spec, the MCP tools and `/v1/endpoints` compile in every language: Instagram's `url` had a lookahead that Go and Rust cannot read. The API's own check is unchanged.
Fixed
- An MCP argument, or a job input, that is an object or a list is refused with `invalid_parameter`. It was sent as the text "[object Object]".
- A bad or suspended key on `/mcp` gets a JSON-RPC error with our message, not a bare 401 that MCP clients take as an OAuth prompt.
Sessions end after 90 days, and a sign-in closes the other links
Changed
- A dashboard session still lasts 30 days from its last use, and now 90 days at most.
- Opening a sign-in link closes every other link sent to the account that has not been used.
- A browser that has signed in to an address is not held to the limit of five emails an hour to that address, so nobody else can use them up.
Fixed
- `/v1/account` showed a key limited to some platforms the usage of every platform. It shows only that key's platforms.
- The sign-up form said where it sent the link using the address on the account, not the one typed.
A job's inputs are checked when it is sent
Changed
- Each input of `POST /v1/jobs` is checked when the job is sent, as a single call's parameters are. A wrong one refuses the job with the error that call would get, naming the input, such as `inputs[3]`. Nothing is charged. Before, it was refused only when it ran, and refunded.
- An account may have as many jobs queued or running as it may have calls at once. One more is refused with `too_many_jobs` (HTTP 429), and nothing is charged.
Fixed
- A number too large for its parameter, such as `lat=91`, is no longer told to page with `cursor`. Only `limit` is.
- A method a path does not take, such as `POST /v1/google-maps/place`, answers `405 method_not_allowed` with an `Allow` header. It was a 400.
- `DELETE /v1/jobs/{id}/results` cancelled the job. Only `DELETE /v1/jobs/{id}` does.
New prices for four calls and the largest pack
Changed
- A page of Google Maps reviews costs 6 credits, from 5.
- A single Instagram post or TikTok video costs 3 credits, from 2, as a profile does.
- A TikTok search for hashtags (type=hashtag) costs 13 credits; a search for videos or accounts stays at 4. A batch job's inputs must all be the same kind.
- The 5,000,000-credit pack costs $2,199, from $1,999.
- Nobody had bought credits yet, so no balance was affected, and no notice was owed.
The privacy notice and the terms say exactly what we do
Changed
- When an account closes, its keys, usage records and jobs are deleted 90 days later. An account that never bought credits is then deleted entirely; the record of a purchase is kept 10 years, for tax. The privacy notice says so; before, it said "as long as the tax rules require".
- The terms now say what a suspension does: the account's keys stop working at once, and we email you why within minutes.
Calls wait in line for a platform's places
Changed
- When a platform's calls at once are full, a call now waits in line for a place, in the order calls arrived, for as long as its own time allows. Before, it asked again at random moments, so a later call could go first.
- A batch job's calls wait in the same line for minutes, not seconds, so a job no longer leaves inputs for later because the places were full for a moment.
- endpoint_busy now means the call's turn did not come within its time. It still costs nothing.
Null, never an empty string
Changed
- A review's author.name and a LinkedIn position's title are null when the source gives none. They were empty strings.
- A field that names the thing, such as an id, a username, a place's name or a profile's full_name, is never empty: a row without one is left out of a list, and a call that would return one is refunded.
Ten new guides, and three migration guides
New
- From Google Maps links to place data: a column of links into ids, addresses, phones and hours, in one batch job.
- Spot when a contact changes jobs: a monthly check of LinkedIn profiles against the company you last knew.
- A business's Google rating every week: new ratings, and new one-star ratings, from the star counts.
- LinkedIn job postings with their full descriptions: a search, then each posting in full.
- Every business of one kind in a city: a grid of Google Maps searches, each place kept once, written to a CSV.
- What a cached answer is: how to tell an answer's age, how long each kind is kept and why, and when to ask for a fresh one.
- Every review of a Google Maps place, page by page, in TypeScript and Python, and a daily check that costs one page.
- Google Maps places into a Google Sheet, with a few lines of Apps Script and the key kept out of the sheet.
- Enriching a list of companies from their LinkedIn pages, as one batch job.
- New Google reviews into a sheet every day, with Make; and LinkedIn company data in a Clay table.
- Migration guides on the Apify, Google Places API and PhantomBuster comparisons: their call beside ours, with the field renames.
Busy is a 429, webhooks are tried for hours, and one account never holds a platform
Changed
- When every place for a platform's calls at once is taken, a call is refused with endpoint_busy, a 429 with Retry-After: 5. It was a 502. A batch job waits instead.
- One account holds at most one fewer of a platform's places than it has, so no one account can take all of them.
Fixed
- A batch job on Instagram, TikTok or LinkedIn company pages that is larger than we can serve at the moment is refused at the start with job_too_large, and nothing is charged. Before, it was accepted, and most of its inputs failed and were refunded.
Improved
- A webhook that fails its quick retries is tried again about 5 minutes, 30 minutes, 2 hours and 12 hours after its job finished, unless your endpoint answered with a 4xx other than 429.
- When every source of an endpoint is out of capacity, the error says so, instead of suggesting a retry.
The Instagram hashtag feed costs 64 credits a page
Changed
- GET /v1/instagram/hashtag costs 64 credits a page, from 4. At 4 it was priced below what a page costs us to serve. Nobody had bought credits yet, so no balance was affected, and no notice was owed.
- The terms now say that a new price applies to credits you already hold once the 30 days' notice has run. The old sentence spoke of a period you had paid for, and credits have no periods.
- The terms now also say that an account is suspended while a payment for it is disputed with a bank, and resumed when the dispute closes in our favour.
Jobs share an account's calls at once, and webhooks go only to public addresses
Fixed
- Two jobs on one account no longer fail each other's inputs with concurrency_limit. All jobs together use one fewer of the account's calls at once than it allows, so a single call always has a place, and a job's call waits for a place rather than failing.
- The low-balance email is sent once the call that crossed the line is answered. A call that failed and was refunded sent it before. A refund that takes the balance back over the line arms it again.
- A job still unfinished a day after it started is given up, as the limits page says, however it was carried on.
Improved
- Each webhook attempt connects only to a public address, checked as the connection is made.
- job_too_large suggests a job size from fixed steps.
Changed
- An MCP batch holds at most 20 messages; a larger one is refused with -32600.
Pages return every row once
Fixed
- A page now returns `limit` rows, and `next_cursor` goes on from the next row. Before, with a `limit` below the source's own page size, the rows between pages were skipped: with limit=5, 15 of each 20 places never came back.
- A list whose source keeps pointing at the same page now ends, instead of repeating it.
- A cursor that was not issued for a page is refused with invalid_cursor before anything is charged.
Improved
- GET https://api.scrapefield.com/v1 answers with where to go next: the docs, the OpenAPI spec, the endpoint list, the errors and the status. /openapi.json on either host goes to the spec.
- A path that is no endpoint answers 404 unknown_endpoint, with or without a key. Without a key it answered 401.
- Demo answers say credits_charged: 0, which is what a demo costs, and their note gives the price of a live call.
Changed
- A batch job's webhook address is forgotten 30 days after the job finishes, with its delivery records. An address often holds a secret. The job still shows that it had a webhook, with url: null.
One LinkedIn job posting in full
curl -H "Authorization: Bearer $SCRAPEFIELD_KEY" \ "https://api.scrapefield.com/v1/linkedin/job?job_id=4468618386"New
- GET /v1/linkedin/job returns one posting by its job_id or URL, with the fields a search leaves null: employment_type, seniority_level, salary where the posting shows one, and the full description. 4 credits.
Improved
- An identifier that cannot be read is refused before anything is charged, with the parameter named: a username with a space, a job id that is not a number, a URL on another site, a short Maps link that carries no place, or text over 2,048 characters. Every identifier has its pattern in the spec and the MCP tools.
Maps photos cost 4 credits a page
Changed
- google-maps/photos costs 4 credits a page instead of 2. At the old price a page could cost more to produce than it sold for. Every other endpoint, and the packs, are unchanged.
Every sample call works
Fixed
- Six endpoint pages showed a sample call the API refused: a place or post identifier was "example". Each now has a real one, and a test checks that every sample passes validation.
- The batch jobs page printed two template placeholders in its curl command instead of the API's address and the key. Its samples now match what the API returns.
- llms.txt now links the batch jobs page, and a page read as Markdown no longer shows its buttons' labels as text.
Batch jobs match single calls
Improved
- Each result line of a job now carries meta: next_cursor, cached and fetched_at. A job over a list endpoint used to keep only the first page; the cursor makes the next one call away.
- The OpenAPI spec now describes the jobs paths: POST and GET /v1/jobs, GET and DELETE /v1/jobs/{id}, and GET /v1/jobs/{id}/results.
Fixed
- An input whose answer suppression emptied is refunded, as a single call costs nothing then.
- The webhook body no longer carries its own webhook field, which always said "pending" at the moment it was sent.
- job_not_found is in the error catalogue, where its docs link pointed.
Webhooks say where the results are
Fixed
- A finished job's webhook always had results_url null. It now has the address to download the results from, as GET /v1/jobs/{id} does.
- A job whose run stopped is picked up again within five minutes. Without API traffic it could wait for the hourly check.
The status page reads recent failures
Changed
- An endpoint reads Degraded when our nightly check of it failed, or when at least three calls to it failed in the last half hour. Before it had 50 calls for a success rate, an endpoint that failed every call still read Operational.
Missing is null everywhere, and a call we cannot serve is free
Changed
- Nullable where the source can be silent: a Google Maps review's rating and publish_time; a LinkedIn job's title, company.name and listed_at; an Instagram post's and comment's timestamp and a comment's text; a TikTok video's and comment's create_time and a comment's text. Before, they were 0, 1970-01-01 or an empty string.
Fixed
- Every call that fails after it has started is refunded. A Google Maps address the source could not read, such as some share links, was a 400 charged in full.
- An Instagram comment time given in seconds came out in January 1970.
- The docs now say that the first page of reviews has up to 8, and each page after it up to 20; and which LinkedIn job fields are null for now.
A key's platforms apply to jobs and usage too
Changed
- A key limited to some platforms lists only their jobs and usage, and gets scope_not_allowed for a job on another platform. Before, it could read and cancel any job on the account.
Fixed
- limit on GET /v1/jobs and GET /v1/usage must be a whole number from 1 to 100 and 1 to 1,000. A negative or non-numeric limit was a 500; it is now a 400 that says the range.
- POST /v1/jobs with a body that is not a JSON object answers which fields are missing, not a 500.
Options that are not built yet are refused before the charge
Fixed
- linkedin/jobs with workplace_type or posted_within_days answered 502 upstream_unavailable after the charge, and the refund followed. Both are documented as not available yet, and they are now refused with 501 not_available_yet before anything is charged.
- The demo answered fresh=true and the two job filters. It now refuses them as a trial key does live, so what works in the demo works with a key.
- Cancelling a running job is final. The run can no longer put it back to running, and each input is refunded at most once.
A LinkedIn profile is 25 credits, and a page of Maps reviews 5
Changed
- linkedin/profile costs 25 credits instead of 10, and google-maps/reviews costs 5 instead of 3. At the old prices both cost more to produce than they sold for. Every other endpoint, and the packs, are unchanged.
A real demo: Ferrari, and Lewis Hamilton
curl "https://api.scrapefield.com/v1/instagram/profile?username=anyone&demo=true"Changed
- Demo mode answers with real data, captured on 3 October 2026: Ferrari on Instagram, TikTok and LinkedIn, the Museo Ferrari in Maranello on Google Maps, and Lewis Hamilton for linkedin/profile. It is still one answer whatever you ask, marked cached, with the time it was fetched.
- A count that the source does not give is null, not 0: the Instagram and TikTok counts, a TikTok video's duration, and a place's location. Before, a missing count came back as 0, which reads as a real number.
Fixed
- google-maps/reviews failed on the first page of every request. It answers again.
- When many calls run at once, a call now waits a moment for capacity instead of failing.
Webhook deliveries, and a secret to check them with
New
- A Webhooks page in the dashboard: each delivery of the last thirty days, with when, where, what your endpoint answered, how many attempts it took and how long. Send the newest delivery of a job again from there: one attempt, no retries, up to 20 an hour.
- Each account has its own webhook signing secret, starting whsec_, on the same page. Check the ScrapeField-Signature header with it.
Fixed
- Webhooks were signed with a secret that no customer could see, so a signature could not be checked. They are signed with your account's own secret now, and you can rotate it on the Webhooks page.
- Revoking a key stops the batch jobs started with it, and refunds the inputs they never reached. Closing an account stops its jobs too.
- The email about a failing webhook opens the Webhooks page, where the delivery can be sent again.
The privacy notice, and a status page that knows sooner
Changed
- The privacy notice says plainly what we keep of what you ask for, and why: to answer the same request again quickly, to measure our sources, and to show working examples on our site. It no longer sets a fixed limit of 24 hours. If you are in the data, we still delete what we hold of it on request and never serve it again.
Improved
- The status page marks an endpoint unavailable as soon as we cannot serve it, rather than after calls have failed. It goes back to operational on its own.
- Pricing and billing say "requests at a time" instead of "concurrent", and say what it means: how many calls your account can run at the same moment. It goes up with the total you have bought and never goes down, so one purchase raises it for good.