ActorStack.dev

80.5% of client ratings are zero, and none of them mean bad

Workana returns a rating for every project, so "100% coverage" would be true. It would also throw away four fifths of the market if you believed it.

By Oswaldo Carabano6 min read

Short answer

Workana returns a client rating on every project, and 80.5% of them are 0.00 — which means the client has no ratings yet, not that they were rated zero. Filtering on the number alone discards four fifths of the market in the belief that you discarded bad clients. Every row therefore carries `client_has_rating`, and that is the field to filter on.

Key points

  • A rating is present on 100% of projects, and 80.5% of those values are 0.00.
  • 0.00 means "no ratings yet". It is an absence encoded as a number, which is the most dangerous kind.
  • `client_has_rating` is the boolean that separates the two cases, and `client_rating_raw` keeps Workana's original string.
  • Publishing "client rating: 100% coverage" would have been true and misleading, which is why the documented figure is 19.4% useful.
  • The same pattern appears elsewhere: an absence encoded as a valid-looking value is worse than a null.
On this page6 sections

Workana returns a client rating on every single project. That means “client rating: 100% coverage” would be a true sentence to put in documentation. It would also cause anybody who believed it to throw away four fifths of the market.

The number, and what it is not

80.5% of client ratings are 0.00, and 0.00 means the client has no ratings yet. It does not mean they were rated zero. There is no way to tell the two apart from the number, and there is no way to tell that the number is doing double duty from looking at it.

So every row also carries:

  • client_has_rating — the boolean that separates the cases.
  • client_rating_raw — Workana's original string.

Why an encoded absence is worse than a null

A null announces itself. Any competent pipeline handles it, and if it does not, it usually fails loudly.

A zero passes every check. It is the right type, it is in range, it survives validation, it aggregates cleanly — and it means something entirely different from what it appears to mean. The query WHERE client_rating >= 4 looks like quality filtering and is mostly history filtering.

The flag that fixes it

the two questions, separated
-- Clients with a track record, rated well
SELECT * FROM projects
WHERE client_has_rating = true AND client_rating >= 4.5;

-- Clients with no history — the majority, and not the same thing as bad
SELECT * FROM projects
WHERE client_has_rating = false;

The second query is the one worth running once, because it shows you how much of the market the first one excluded. Four fifths is a lot to discard by accident.

Reporting coverage honestly

The documented figure for client_rating is 19.4%, not 100%. That is the principle this project applies throughout: coverage is how often a field carries useful information, not how often the key exists.

Two other fields on the same row follow the same rule. client_payment_verified is true on 18.9% — present everywhere, meaningful when true. is_hourly is true on 11.7%. Reporting those as “100% coverage” would be equally true and equally useless.

The client signals that do work

FieldUsefulHow to read it
client_country_code100%Always there. The most reliable dimension in the dataset.
client_payment_verified18.9% trueA real positive signal when set. Absence is not a negative.
client_has_rating100%The gate for any rating filter.
client_rating19.4%Only meaningful with the gate applied.
last_client_message_raw51.7%Presence suggests an engaged client.
client_plan0.4%Too rare to build on.

Practical filtering

For finding good clients to work with, the useful combination is client_payment_verified = true plus a fresh total_bids that is still low — a verified client whose project has few proposals is a better opportunity than a highly rated client whose project already has thirty.

And since proposal counts move within hours, that filter only works on fresh rows. Set maxCacheAgeHours: 0 when the decision is whether to bid.

Frequently asked questions

Why do most Workana clients have a 0.00 rating?
Because they have no ratings yet. Workana returns 0.00 as its representation of "no history", which is indistinguishable from a genuine zero unless you also read `client_has_rating`.
How do I filter for well-rated clients?
Filter `client_has_rating = true` first, then apply a threshold to `client_rating`. Applying the threshold alone removes the 80.5% who simply have no history, which is not the same population as badly rated clients.
What is the real coverage of the rating field?
100% of rows carry a value and 19.4% carry a useful one. The documented figure is 19.4%, because the other number describes the key rather than the data.

Sources

Every URL below was requested and returned a page on the date shown.

  1. Operator claimchecked 19 Aug 2026
    Workana Projects & Client Demand Scraper — Actor README and input schemaActorStack / Apify Store
A laptop showing lines of code on a wooden desk in a dimly lit room.
WorkanaMeasured

Filters that do nothing

`budget_min`, `is_hourly`, `duration`, `payment_verified` and nine others return HTTP 200 and change nothing. One of them makes the result set bigger.

7 min
A white measuring tape curving across a dark background, showing the numbers 15 to 45.
WorkanaMeasured

Proposal velocity

Measured across 401 projects: competition on a freelance listing has a half-life measured in hours, which makes a stale row a wrong row.

6 min
Paper receipts and printed documents arranged on a desk beside office stationery.
WorkanaExplainer

Parsing budgets

"USD 1,000" and "USD 1.000" are both one thousand. "Less than USD 50" has no lower bound. Both facts break naive budget parsing in ways that survive review.

8 min