TextLens API for Python

Add text analysis to your Python app in 5 lines. Readability grades (8 formulas), sentiment scoring, keyword extraction, and SEO analysis — no textstat, VADER, or spaCy to install and configure.

From the team behind textlens — 96 npm downloads/week

import requests

result = requests.post(
    'https://api.ckmtools.dev/v1/analyze',
    headers={'X-API-Key': 'your_key'},
    json={'text': 'Your content here...'}
).json()

print(result['readability']['consensus_grade'])  # Grade 8
print(result['sentiment']['label'])              # positive
print(result['keywords']['top_5'])               # [content, quality, ...]
Join the Waitlist

What you get

8 Readability Formulas

Flesch-Kincaid, Gunning Fog, SMOG, Coleman-Liau, ARI, Dale-Chall, Linsear Write, plus a consensus grade. No single Python library covers all eight.

Sentiment + Keywords

AFINN sentiment scoring for long-form content — label, score, and confidence. TF-IDF keyword extraction with relevance scores. SEO quality scoring.

Zero Library Dependencies

No NLTK corpus downloads (150MB+), no spaCy model files (12MB–560MB), no pip deps beyond requests. Works in serverless, CI/CD, and containers.

The response

One endpoint returns everything you need:

{
  "readability": {
    "fleschKincaidGrade": 8.2,
    "gunningFog": 10.1,
    "smog": 9.4,
    "colemanLiau": 11.3,
    "ari": 9.7,
    "daleChall": 7.8,
    "linsearWrite": 8.5,
    "consensusGrade": "Grade 9",
    "fleschReadingEase": { "score": 62.3, "interpretation": "Standard" }
  },
  "sentiment": {
    "label": "positive",
    "score": 4.2,
    "confidence": 0.71
  },
  "keywords": [
    { "word": "content", "score": 5.1, "count": 4, "density": 1.87 },
    { "word": "readability", "score": 4.8, "count": 3, "density": 1.40 }
  ],
  "seo": { "score": 74, "grade": "B" },
  "statistics": { "words": 342, "sentences": 18, "paragraphs": 5 },
  "meta": { "processing_time_ms": 14 }
}

Python patterns

requests — most common recommended
import requests
import os

class TextLensClient:
    BASE_URL = 'https://api.ckmtools.dev/v1/analyze'

    def __init__(self, api_key: str):
        self.session = requests.Session()
        self.session.headers.update({'X-API-Key': api_key})

    def analyze(self, text: str) -> dict:
        response = self.session.post(self.BASE_URL, json={'text': text})
        response.raise_for_status()
        return response.json()

client = TextLensClient(os.environ['TEXTLENS_KEY'])
result = client.analyze(article.body)

print(f"Grade: {result['readability']['consensusGrade']}")
print(f"Sentiment: {result['sentiment']['label']}")
print(f"SEO score: {result['seo']['score']}/100")
httpx — async client
import httpx
import asyncio
import os

async def analyze_text(text: str) -> dict:
    async with httpx.AsyncClient() as client:
        response = await client.post(
            'https://api.ckmtools.dev/v1/analyze',
            headers={'X-API-Key': os.environ['TEXTLENS_KEY']},
            json={'text': text}
        )
        response.raise_for_status()
        return response.json()

# Analyze multiple documents concurrently
async def batch_analyze(texts: list[str]) -> list[dict]:
    tasks = [analyze_text(t) for t in texts]
    return await asyncio.gather(*tasks)

results = asyncio.run(batch_analyze(articles))
urllib — stdlib, zero pip deps
import urllib.request
import json
import os

def analyze(text: str, api_key: str) -> dict:
    data = json.dumps({'text': text}).encode('utf-8')
    req = urllib.request.Request(
        'https://api.ckmtools.dev/v1/analyze',
        data=data,
        headers={
            'Content-Type': 'application/json',
            'X-API-Key': api_key,
        },
        method='POST'
    )
    with urllib.request.urlopen(req) as resp:
        return json.loads(resp.read())

result = analyze(document, os.environ['TEXTLENS_KEY'])
print(result['readability']['consensusGrade'])

Why not textstat + VADER + spaCy?

Three packages, three APIs, three version conflicts. textstat covers readability but skips sentiment. vaderSentiment covers sentiment but not readability. spaCy requires a model download (12MB to 560MB) before you can do anything. And none of them give you SEO scoring. TextLens API covers all of it in a single HTTP call — no corpus downloads, no model files, no dependency resolver headaches. The same endpoint works from Python, Ruby, Go, or any language with an HTTP client.

Join the Waitlist

TextLens API is in development. Join the waitlist to get notified at launch.

Backed by the textlens npm package — 96 downloads/week.

Get Early Access

$0 — no credit card required

Pricing

Free

$0 /mo
  • 1,000 requests/mo
  • 10 req/min rate limit
  • 5,000 char max per request
Get Started

Starter

$9 /mo
  • 25,000 requests/mo
  • 60 req/min rate limit
  • 25,000 char max per request
Subscribe

Enterprise

$99 /mo
  • 500,000 requests/mo
  • 300 req/min rate limit
  • 500,000 char max per request
Subscribe

Using Ruby? See Ruby-specific examples →

Using Go? See Go-specific examples →

See all Python library comparisons →