Back to Tools

SERP Clustering API

Use cases

Integrating SERP clustering into automated keyword pipelines Building internal tools that consume clustering results via API Batch processing multiple keyword sets programmatically

A FastAPI service that clusters keywords based on common organic result URLs from ValueSERP CSV exports.

Builds link and query intersection maps, pairs queries sharing a configurable minimum number of common URLs (default 4), then groups them into numbered clusters sorted by overlap count.

Returns JSON with cluster arrays, total cluster count, and threshold used.

Platform

Python script (requires Python 3.x)

Input

ValueSERP batch export CSV (must contain search.q and result.organic_results.link columns)

Output

JSON object containing serp_clusters array, total_clusters count, and common_urls_threshold.

View Source

Features

  • REST API with Swagger UI and ReDoc auto-documentation
  • Configurable common_urls threshold (default 4)
  • Expects ValueSERP columns: search.q and result.organic_results.link
  • Deduplicates and lowercases queries before clustering
  • JSON response with cluster ID, similar_query, queries array, and common URLs list
  • Docker and gunicorn deployment examples included

How to use

  1. 1 Start the server with uvicorn app:app --reload (runs on port 8000)
  2. 2 POST a ValueSERP CSV to /cluster-serps with optional common_urls parameter
  3. 3 Receive JSON response with clustered keyword groups and shared URLs

Frequently asked questions

Where does the input CSV come from and what must it contain?
It is built for ValueSERP batch exports, which flatten the JSON into dotted column names. Only two columns are read: search.q (the query) and result.organic_results.link (each ranking URL), one row per query-URL pair. Any other columns in the file are ignored, but those two names must match exactly or the request fails.
Why does a keyword only ever appear in one cluster?
Clustering is greedy: once a query has been paired into a cluster it is marked processed and excluded from all later comparisons. A keyword whose SERP overlaps several groups joins whichever it is compared against first, so the result is order-dependent and borderline keywords can land in different clusters if you change or reorder the input set.
How should I choose the common_urls threshold?
It is the minimum number of identical organic URLs two queries must share to be clustered, defaulting to 4. Matching is on exact URL strings after deduplication, so with top-10 SERPs the default requires roughly 40 percent overlap. Lower it for looser clusters, raise it if unrelated keywords are being merged, and scale it up if your export contains more than 10 results per query.
Will it handle very large keyword sets?
The algorithm compares every query against every other query in memory, so runtime grows quadratically with the number of unique queries. Small and mid-sized exports return quickly; for very large sets expect the request to take noticeably longer rather than fail.
Is the API safe to expose publicly?
There is no authentication, rate limiting or file size restriction built in; anyone who can reach the endpoint can upload CSVs. Run it locally, behind a reverse proxy with auth, or on a private network. The README includes Docker and gunicorn examples for deployment.

Need something built for your business?

This tool started as bespoke client work. I build custom scripts, data pipelines, and full apps for SEO and product data problems that off-the-shelf tools don't solve.

Tell Me What You Need