Unprofane

Google Is Shutting Down Perspective API on December 31. Here’s What Breaks, and When

The scary part isn’t an error page. It’s a comment section that keeps running with nobody checking it.

A cover in ink: Perspective API shuts down, here’s what breaks, beside a comments queue on January 1, 2027 where every toxicity check gets no answer and every comment is published

December 31, 2026 is the last day Google’s Perspective API will answer. Jigsaw’s own notice puts it plainly: the service “will remain active until December 31, 2026.” There’s no extension and no migration help from Google.

I went through what happens to the tools built on top of it, and the answer surprised me. Most of them won’t crash on January 1. They’ll keep accepting comments and quietly stop checking them. (AI-assisted draft; I checked each claim against its source.)

So here’s the whole picture, by date, with the steps I’d take if Perspective sits anywhere in my stack.

The dates

A timeline: February 2026, the last usage and quota requests answered; December 31, 2026, the last day the API answers; January 1, 2027, nothing after it

From Google's notice at perspectiveapi.com

February 2026: requests closed. Google stopped taking usage and quota increase requests in February. If your traffic grew this year, you’re living on whatever quota you already had. The FAQ puts the default at an average of one query per second per project.

Now until December 31: it still works. Nothing has changed in the API itself. Same endpoint, same JSON, still free. That’s the catch, honestly. There’s no warning in the response, so nothing in your logs will remind you.

January 1, 2027: no more answers. Google hasn’t said what the endpoint will return after that, whether it’s an error code, a timeout or a domain that doesn’t resolve. So plan for all three.

What actually breaks

A lot of Perspective calls don’t come from code you wrote. They come from comment systems, forum plugins and old scripts, and each of those decided long ago what to do when Google doesn’t answer. I read the code for two that ship it built in.

Coral by Vox Media (a comment platform for news sites). Coral’s toxic comment filter sends each new comment to Perspective and holds anything above your threshold for a moderator. If the call fails, its code logs “could not determine comment toxicity” and moves on. The comment goes through the rest of the pipeline as if it were clean. No alert, no error for the reader, no item in the queue.

Coral’s toxic comment filter in toxic.ts: the catch block rethrows a ToxicCommentError and otherwise logs could not determine comment toxicity and returns

Coral's toxic.ts on GitHub: a failed call is logged, and the comment moves on

Discourse’s Perspective plugin. The official plugin flags posts above a toxicity threshold and can warn people while they type. Two failure paths here. If the network call itself fails, it raises an error and the post isn’t flagged. And if Google answers with an error body instead of scores, the plugin’s parser falls back to a score of 0.0 for every post. Zero never crosses a threshold, so nothing gets flagged.

Your own code. If you call the API directly, what happens depends on one line you probably wrote years ago: the except around the call. A lot of moderation code is written to fail open on purpose, because nobody wants a Google outage to block every comment. That was the right call for a five-minute outage. It’s the wrong call for a permanent one.

Research pipelines. If a paper, a dataset or a dashboard depends on fresh Perspective scores, it stops being reproducible on new text in January. Scores you already stored still exist, but you can’t add comparable ones.

Who should care

  • Newsrooms and publishers running Coral with the toxic comment filter on.
  • Discourse forums with the discourse-perspective-api plugin enabled.
  • Apps calling commentanalyzer.googleapis.com from a backend, a queue worker or a serverless function.
  • Teams with a dashboard or a study built on TOXICITY scores.

If you’re not sure, the next step tells you in a minute.

The steps, in order

1. Find every call

Search your code, your config and your infrastructure for the host name:

grep -rn "commentanalyzer" .

Also check the admin settings of anything you didn’t write. In Coral it’s under Configure, Moderation, Toxic Comment Filter. In Discourse, type “perspective” into the admin settings filter. And look for the API key in your Google Cloud project, since forgotten scripts love to share one.

2. Make failures loud

Before you replace anything, change what happens when the check doesn’t answer. Even if you switch next week, this protects you from the next outage too.

def check_comment(text):
    try:
        return score(text)  # your current toxicity call
    except Exception:
        log.error("toxicity check failed, holding comment for review")
        return None  # treat None as "send to the review queue"

The rule is simple: an unanswered check goes to a human or to a hold, never straight to publish. And add an alert on the error count, so a dead endpoint pages someone instead of filling a log nobody reads.

3. Save what your thresholds mean

Your thresholds were tuned against Perspective’s scale, probably over months. Before December, export a sample of recent comments with the scores Perspective gave them and what your moderators decided. Any replacement will score on its own scale, and that sample is how you’ll find the new threshold that flags about the same share of comments.

4. Pick a replacement and run it side by side

Run the new service in parallel for a week or two, logging both answers, before you switch. The main options, with their trade-offs:

  • OpenAI’s moderation endpoint. Free, and it scores harassment, hate, self-harm, sexual content and violence. It has no profanity category, so swearing on its own won’t move it.
  • Azure AI Content Safety. Hate, sexual, violence and self-harm on a severity scale. Needs an Azure subscription; plain profanity that doesn’t target a group sits at a low level of hate.
  • Discourse AI. For Discourse forums, its AI triage can classify posts with an LLM prompt you write. Discourse-hosted sites can use Discourse’s own hosted small LLM; self-hosted forums need a third-party one.
  • A word list. Coral and Discourse both have banned words built in. It’s free and predictable, but it misses disguised spellings and can block innocent words.
  • A drop-in for Perspective’s API. Full disclosure, I built Unprofane, which answers Perspective’s own requests on the same path with the same JSON, so Coral moves by changing an endpoint and a key, and Discourse by a one-line change to its plugin. The migration guides cover each client.

None of these is a perfect clone, since each model scores differently. If you mostly care about threats and harassment and want free, OpenAI is a reasonable first test. If you have an LLM in your forum already, Discourse AI keeps everything in one place.

5. Switch before December, keep a way back

Don’t plan the switch for the last week of the year, when half your team is out. Pick a date in November, keep the old key working until the end of December, and make the endpoint a config value so rolling back is a settings change, not a deploy.

6. Clean up in January

After the switch, delete the Perspective key from your Google Cloud project and remove the old code path. A dead integration that still “works” is how the failure in step 2 sneaks back in a year later.

The short version

Perspective’s last day is December 31. The real risk isn’t a broken page, it’s moderation that silently turns off. Find your calls, make failures hold comments instead of publishing them, save your old scores, test a replacement in parallel and switch in November.

If you’re in the middle of this and hit something odd, tell me in the comments. I’d like to know which tools I missed.

Good luck with the switch, and thanks for sticking with me to the end :)

I’m the developer behind Unprofane, a profanity and toxicity API.

Catch what Perspective misses. Change one line.

A profanity and toxicity API your users can’t spell their way around, on Perspective’s own path and JSON. Point your client at it and your queue gets better, not quieter.

89.0%
of toxic texts caught at a 7.0% false-alarm rate. Perspective, at the same rate: 58.4%.
0 of 549
innocent words and names flagged on the Scunthorpe Test’s public split: Scunthorpe, cockatoo, Dickinson.

How it was measured, on 9,029 held-back texts.

Hobby50% off for 3 months

$4.50a month for 3 months, then $9

25,000 checks a month, every language and disguise included.

Get your API key

Keep reading

Every post