Skip to content

Third-party spam checking

Charcha’s spam defence is eight layers deep, and seven of them stay inside the Cloudflare account that already runs your Worker. The eighth posts a comment to a company that is not you. It is off until you switch it on, and this page is about it.

What leaves your Worker is stated here before the two commands that enable it. That order is a commitment rather than a formatting choice.

Nothing about your readers leaves your account while this is off, and that stays true after you switch it on for every comment the free layers settle. Layers 1, 2, 4, 5 and 6 transmit nothing anywhere. Layer 3 makes one subrequest to Cloudflare, and layer 7 sends the text of a comment to a Cloudflare model running on your own account. Only layer 8 posts anything to a company that is not you or your infrastructure provider.

Who Akismet, run by Automattic
Default Off. Nothing is asked for at deploy time, and nothing is sent until you set two values
What it can do Hold a comment for review, or vouch that it checked one and found it clean. It can never refuse one, and below is why
What it costs Akismet’s Pro plan is “$9.95 per month, billed yearly” for “500 spam calls/mo, up to 1 site”. Business is “$49.95 per month, billed yearly” for “5000 monthly spam checks”. The Personal plan is pay-what-you-can and asks that your site carries no ads, sells nothing and promotes no business (pricing, personal, checked 2026-07-29)
Where it runs Last, so it only ever sees comments the seven free layers could not decide

Every comment that reaches layer 8 is posted to Akismet’s comment-check endpoint carrying:

Field What it is
user_ip The commenter’s IP address, in full. Not the hash Charcha stores, the address itself. It is one of Akismet’s three required parameters, so it cannot be left out
comment_author The name they typed
comment_author_email Their email address, only if they gave one. The field is optional in Charcha and omitted entirely when it is blank
comment_content The full text of the comment
user_agent Their browser’s user-agent string
referrer The page their browser said they came from
permalink The page they commented on, built from your site’s address setting and the page key this Worker derived, never from the address the comment reported
comment_type comment or reply
comment_date_gmt When it was submitted
blog Your site’s home page URL, from the same setting
api_key Your Akismet key, which is what identifies the account

Nothing else. Akismet documents a dozen further parameters, among them comment_author_url, user_role, blog_lang, honeypot_field_name, comment_context and the whole of a PHP request’s $_SERVER, and Charcha sends none of them. The list above is written out field by field in the source rather than assembled from whatever a request happens to carry, so nothing can reach Akismet by accident.

Akismet says it keeps spam-related data for “between two weeks and ninety days for the vast majority”, and that it does not sell it (privacy policy, checked 2026-07-29). That is Akismet’s statement rather than Charcha’s, and it is Akismet’s to change.

If your site has one, this is the paragraph this feature obliges you to add:

Comments submitted on this site are checked for spam by Akismet, a service run by Automattic. Akismet receives the commenter’s IP address, name, email address if one was given, the text of the comment, their browser’s user-agent string, the page they were referred from and the address of the page they commented on. See Akismet’s privacy policy.

It covers the reader whose comment never appears, too, which is the easy thing to miss. The check happens before the comment is stored, so a comment you go on to delete has already been sent.

Two values, both together or the feature stays off. They are set in two different places, because only one of them is a credential.

The key is a secret. AKISMET_API_KEY comes from your account at akismet.com. Setting a secret has the click path through the Cloudflare dashboard, and from a terminal it is:

Terminal window
pnpm wrangler secret put AKISMET_API_KEY

Your site’s address is a setting. The Setup tab in your dashboard has a field for it, under Your site’s address. It is your site’s home page, https://example.com, or https://you.github.io/blog if your site lives at a path. It is neither optional nor guessable. Akismet requires it and matches it against the sites authorised on your key, and Charcha has nowhere else to get it from: your Worker’s own address is a workers.dev URL rather than your site, and the URL the embed reports is chosen by whoever posted the comment. If you set CHARCHA_SITE_URL as a secret before it became a field, that keeps working and the tab says so.

Setting one without the other does not half-enable anything. The layer stays off, and your Worker’s log carries one line naming the missing half.

Delete AKISMET_API_KEY, from the screen you added it on or with one command. Nothing else changes. The other seven layers do not know layer 8 exists, comments carry on arriving, and your moderation queue is unaffected.

Terminal window
pnpm wrangler secret delete AKISMET_API_KEY

It can only hold a comment, never refuse one

Section titled “It can only hold a comment, never refuse one”

Whatever Akismet answers, the worst that happens to a comment is that it is held for review with provider: akismet as its reason in your moderation queue. Charcha refuses nothing on a third party’s say-so, for three reasons.

It is a probability rather than a rule. A comment the honeypot catches is caught by something you can read and check for yourself. A comment Akismet flags is flagged by a model you cannot inspect, about a site it has never seen.

A refused comment is never stored, so nobody ever finds out it was wrong. A held one sits in your queue, where you can disagree with it in one keystroke.

And the same rule already governs Charcha’s own classifier, which learns from your moderation decisions. Trusting a stranger’s judgement above your own would be a strange way round.

Akismet can also answer X-akismet-pro-tip: discard, meaning blatant spam, safe to throw away without saving. Charcha still only holds those. The reason token reads provider: akismet-discard so you can triage them first, and that is the whole of the difference it makes. Acting on it would mean layer 8 could refuse a comment, which would mean it could no longer be skipped for a comment some earlier layer had already held, and that skip is what stops an anonymous visitor spending your monthly allowance on answers nobody reads.

The answer that is not a hold is worth its own section, because it is the one thing a third party can do here that Charcha’s own checks mostly cannot.

Akismet coming back “clean” is a real verdict from a real classifier. That is different from silence, and Charcha keeps the two apart: silence is also what a layer that never ran produces, so it can never count as approval. A positive answer is recorded as a vouch.

By default a vouch changes nothing you would notice. The comment lands in your queue like everything else, and you read it.

It matters only if you set your moderation policy to also publish what your spam service calls clean, which puts a vouched comment straight onto the page. Even then:

  • Any doubt beats it. A vouch is collected separately from the holds and consulted only after every layer has run, so one review or reject from any of the seven layers ahead wins, no matter which came first.
  • A vouching layer cannot silence the layers after it. It does not short-circuit the run.
  • Silence is not a vouch. Akismet switched off, timed out, erroring, or answering “unknown” all produce nothing, and this policy does not act on nothing.

That last property is the one worth holding on to. On the deployment most likely to reach for this setting, the one with nothing configured yet, there is no provider to vouch, so it publishes nothing at all. It fails towards holding. Moderation covers choosing it.

Nothing, from your reader’s point of view. Layer 8 fails open: a timeout, a network failure, a 5xx, an expired subscription, a suspended key, or a site Akismet does not recognise all produce no opinion, exactly as if the layer were switched off. Nobody loses a comment because a third party had a bad day, and no comment is held with Akismet’s name on it for a check Akismet never performed.

The trade is that all of those are quiet, so Charcha writes one log line per distinct problem to your Worker’s log, carrying the debug help Akismet returned and any account alert it sent. An expired subscription is code 10402. Overuse is 10009. If a layer you are paying for has stopped working, that line is how you find out, because a quiet week and a dead key look identical from your queue.

CleanTalk and StopForumSpam were both named alongside it and neither is built. One adapter is what proves the seam works, a third is speculative until somebody asks for it, and every provider added is another company you have to explain to your readers.