Google's Jigsaw is turning off Perspective API. It already stopped accepting new users earlier this year, and after December 31, 2026 it stops answering everyone else.
If you run comments, a forum or a chat with Perspective behind it, that's a few weeks from now. Coral's toxic comment filter, the Discourse plugin, Drupal modules and plenty of homemade scripts all call the same endpoint:
https://commentanalyzer.googleapis.com/v1alpha1/comments:analyze This post shows how to point that call somewhere else without rewriting anything.
Disclosure: this is written by the team behind VigiMod, the API used in the examples. It's free during the beta.
The short version
VigiMod exposes the same path and accepts the same JSON. You change the host and the key:
- https://commentanalyzer.googleapis.com/v1alpha1/comments:analyze?key=PERSPECTIVE_KEY + https://api.vigimod.com/v1alpha1/comments:analyze?key=VIGIMOD_KEY The request body stays the same, and the response has the same shape (attributeScores.<ATTRIBUTE>.summaryScore.value), so the code that reads it doesn't change either.
Before and after in Python
Before:
import requests r = requests.post( "https://commentanalyzer.googleapis.com/v1alpha1/comments:analyze", params={"key": PERSPECTIVE_KEY}, json={ "comment": {"text": message}, "languages": ["en"], "requestedAttributes": {"TOXICITY": {}, "INSULT": {}, "THREAT": {}}, }, ) scores = {k: v["summaryScore"]["value"] for k, v in r.json()["attributeScores"].items()} flagged = scores["TOXICITY"] >= 0.8 After:
import requests r = requests.post( "https://api.vigimod.com/v1alpha1/comments:analyze", # new host params={"key": VIGIMOD_KEY}, # new key json={ "comment": {"text": message}, "languages": ["en"], "requestedAttributes": {"TOXICITY": {}, "INSULT": {}, "THREAT": {}}, }, ) scores = {k: v["summaryScore"]["value"] for k, v in r.json()["attributeScores"].items()} flagged = scores["TOXICITY"] >= 0.8 With curl
curl -s "https://api.vigimod.com/v1alpha1/comments:analyze?key=$VIGIMOD_KEY" \ -H "Content-Type: application/json" \ -d '{"comment": {"text": "you are an idiot"}, "requestedAttributes": {"TOXICITY": {}, "INSULT": {}}}' { "attributeScores": { "TOXICITY": {"summaryScore": {"value": 1.0, "type": "PROBABILITY"}}, "INSULT": {"summaryScore": {"value": 0.9998, "type": "PROBABILITY"}} } } With Node.js
const r = await fetch( `https://api.vigimod.com/v1alpha1/comments:analyze?key=${process.env.VIGIMOD_KEY}`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ comment: { text: message }, requestedAttributes: { TOXICITY: {}, PROFANITY: {} }, }), }, ); const { attributeScores } = await r.json(); const toxicity = attributeScores.TOXICITY.summaryScore.value; Coral, Discourse and Drupal
Coral. In Admin → Configure → Moderation, under the Toxic Comment Filter, set the Perspective endpoint to https://api.vigimod.com/v1alpha1 and paste your VigiMod key. If your Coral version has a timeout for the check (older versions use TALK_PERSPECTIVE_TIMEOUT, 300 ms by default), give it some room, around 1000 ms: when the answer arrives late, Coral skips the score.
Discourse. The official Perspective plugin calls Google's host directly and has no setting for it. In your copy of the plugin, replace commentanalyzer.googleapis.com with api.vigimod.com, and put the VigiMod key in perspective_google_api_key.
Drupal and everything else. Any module or script that lets you set the Perspective URL works as is. If the URL is hardcoded, it's one line.
Which attributes are supported
| Perspective attribute | Scored from |
|---|---|
| TOXICITY | toxicity |
| SEVERE_TOXICITY | hate and threats (a message that is only rude stays under 0.7) |
| IDENTITY_ATTACK | hate |
| INSULT | insults |
| THREAT | threats |
| SEXUALLY_EXPLICIT | sexual content |
| PROFANITY (and OBSCENE) | swearing and vulgar language |
| FLIRTATION | flirting and sexual advances |
| SPAM | unsolicited advertising |
The _EXPERIMENTAL names are accepted too. Attributes that aren't scored (ATTACK_ON_AUTHOR, INCOHERENT, INFLAMMATORY, LIKELY_TO_REJECT, UNSUBSTANTIAL and the bridging ones) return a 400 error that names them, rather than a made-up number.
What to check before switching
A few things behave differently, and it's better to know them up front:
- The scores come from a different model. They're rescaled so that 0.7 is VigiMod's tuned threshold for each attribute, which means thresholds between 0.7 and 0.9 behave sensibly. Still, watch a few days of real comments before trusting your old numbers blindly.
-
context.entriesis read by the model. The previous messages change the scores, so replies and quotes are judged together with what came before. - Long comments (over 1,000 characters) are scored in parts, up to 10,000 characters. Each part counts as one message for the rate limit, and
spanScoresgives you the score of each part. - Nothing is stored. Comments are scored and discarded.
comments:suggestscoreis accepted for compatibility, but the suggested scores aren't kept. - Languages: any language code is accepted. The model understands 26 languages and works best in English, Italian, Spanish, French, German and Portuguese.
Beyond Perspective
The compatible endpoint is the quick switch. The same key also works with VigiMod's own /moderate endpoint, which adds a few things Perspective never had:
- custom rules written as plain sentences ("no selling accounts", "no spoilers"), each with its own score;
- per-user spam detection;
- policies that turn scores into actions (warn, timeout, ban), with a review queue for moderators and webhooks.
There's also a public benchmark on HateCheck and Multilingual HateCheck in six languages, with every prediction downloadable: vigimod.com/en/benchmark.
Getting a key
- Create a free account at vigimod.com and generate an API key.
- Swap the host and the key.
- Watch a few days of real traffic and adjust thresholds if needed.
The full migration guide, with the attribute table and per-tool settings, is at vigimod.com/en/perspective-api-alternative. Questions go to support@vigimod.com, or leave them in the comments here.
