API Documentation
The Bias Meter API is free to use with rate limits. All endpoints return JSON following
the bias-audit.v1 schema.
Base URL
https://bias-meter.<your-domain>.workers.dev
Replace with your deployed Cloudflare Workers domain.
Rate Limits
To prevent abuse, the API enforces the following limits:
- 10 requests per minute per IP address
- 100 requests per hour per IP address
- Rate limit headers are included in every response
When rate limited, the API returns 429 Too Many Requests with a
Retry-After header.
Endpoints
Returns service status and version information.
Response
{
"status": "ok",
"service": "bias-meter",
"version": "1.0.0",
"runtime": "cloudflare-workers",
"timestamp": "2026-02-14T12:00:00.000Z"
}
Fetches the given URL, extracts content, and returns a full bias audit report. This is the primary endpoint for analyzing web pages.
Parameters
| url | required | The fully-qualified URL to analyze (must include protocol) |
Example Request
curl "https://bias-meter.example.workers.dev/api/bias-audit?url=https://example.com/article"
Response Schema (bias-audit.v1)
{
"overall": {
"bias_risk_score": 34, // 0-100
"rating_label": "mild", // low | mild | moderate | high | very_high
"confidence": 0.62 // 0.0-1.0
},
"dimension_scores": [
{
"dimension": "Language & Tone",
"score": 28,
"weight": 0.18,
"summary": "Detected minor language & tone issues...",
"signals": [
{
"type": "loaded_language",
"severity": 30,
"count": 3,
"excerpts": [
{
"text": "ridiculous",
"context": "...this ridiculous claim...",
"location": null
}
],
"description": "Use of emotionally charged language"
}
]
}
// ... 4 more dimensions
],
"key_findings": [
{
"priority": "high",
"category": "Language & Tone",
"description": "Personal attacks detected",
"excerpts": [...],
"suggested_fix": "Focus on arguments rather than character."
}
],
"suggestions": [
{
"priority": "high",
"category": "Evidence Quality",
"action": "Add primary source citations for factual claims.",
"expected_impact": "Enables verification and increases credibility."
}
],
"extracted_artifacts": {
"url": "https://example.com/article",
"title": "Article Title",
"headings": [...],
"outbound_links": [...],
"citations": [...],
"word_count": 2450,
"content_hash": "a1b2c3...",
"extracted_at": "2026-02-14T12:00:00.000Z"
},
"debug": {
"extraction_method": "cheerio",
"timings_ms": {
"fetch": 1200,
"extract": 45,
"analysis": 12
}
}
}
Analyze pre-extracted content. Use this when you've already fetched and processed
the HTML yourself. Requires text and html fields at minimum.
Request Body
{
"url": "https://example.com/article", // optional
"title": "Article Title", // optional
"text": "The full plain text...", // required
"html": "<html>...</html>", // required
"headings": [], // optional, auto-extracted if empty
"links": [], // optional
"citations": [] // optional
}
Example Request
curl -X POST "https://bias-meter.example.workers.dev/api/bias-audit" \
-H "Content-Type: application/json" \
-d '{"text": "This is obviously wrong...", "html": "<p>This is obviously wrong...</p>"}'
Error Responses
All errors follow this format:
{
"error": "Error description",
"message": "Additional details" // optional
}
| 400 | Missing or invalid parameters |
| 429 | Rate limit exceeded. Check Retry-After header. |
| 500 | Internal error (fetch failure, parse error, etc.) |
CORS
All API endpoints include permissive CORS headers (Access-Control-Allow-Origin: *),
so you can call the API directly from browser-side JavaScript.
Client Libraries
No official client libraries yet. The API is a simple REST interface — use fetch(), curl, or any HTTP client.
JavaScript Example
const response = await fetch(
'https://bias-meter.example.workers.dev/api/bias-audit?url=' +
encodeURIComponent('https://example.com/article')
);
const report = await response.json();
console.log(report.overall.bias_risk_score); // 0-100
console.log(report.overall.rating_label); // "low" | "mild" | ...
Python Example
import requests
resp = requests.get(
"https://bias-meter.example.workers.dev/api/bias-audit",
params={"url": "https://example.com/article"}
)
report = resp.json()
print(f"Bias score: {report['overall']['bias_risk_score']}/100")
print(f"Rating: {report['overall']['rating_label']}")