How to find active Medium publications and rank them by engagement
Find Medium publications by keyword and score each by followers, posting cadence, claps per 1,000 followers and paywalled share, in Python or cURL.
datagrit › Guides › Google Trends Keyword Ranker and Compare Tool
GuideRank up to 100 keywords on one comparable Google Trends scale, per country, with regions and related queries, in Python or cURL and without a browser.
Published 2026-10-08 · uses the Google Trends Keyword Ranker and Compare Tool Actor
Anyone who has tried to choose between a dozen keywords on Google Trends has hit the same wall. The comparison box accepts five terms. Every chart is rescaled so that its own highest point is 100. If you read the first five keywords in one chart and the next five in another, a 60 in the first chart and a 60 in the second mean different things, and the two lists cannot be sorted together. Content teams, SEO analysts, product marketers and researchers who need a ranking of 30 or 50 candidates end up screenshotting charts and guessing.
This guide shows how to get one ranked table for a long keyword list, per country, using the Google Trends Keyword Ranker Actor, and explains the method so you can judge how far to trust the numbers.
Google Trends returns relative interest, not search counts. The value of a point is the share of searches for the term in the chosen location and time, divided by the highest such share in the chart, times 100. Two properties follow from that:
That second point is the way out. If keyword rust appears in both chart A and chart B, the ratio between its two averages tells you how to rescale chart B onto the scale of chart A. The Actor automates exactly that.
Keywords are read in groups of five. The first group is the reference. For every later group, the Actor repeats one keyword from the first group as an anchor, reads the group together with the anchor, and rescales the group by the ratio between the anchor's readings in the reference chart and in the new chart. The anchor is the keyword at the median level of the first group, so it is neither the strongest term, which would squash the others in the new chart, nor the weakest, which would be noisy.
The weak link in such a chain is the anchor's volume. When the anchor has little search interest, rounding to whole numbers makes the ratio unreliable. So every row carries scaleQuality:
exact for the first group, which needs no conversion.good when the anchor had enough volume in both charts for a stable ratio.coarse when it was thin, or when the keyword's own values average below 3 on the 0 to 100 scale, so the placement is approximate.unlinked when it was too thin to link at all. These keywords keep their own 0 to 100 values but get no rank.The run message adds the counts, for example Scale quality: 3 exact, 1 good, 3 coarse, 0 unlinked, so a job that fails to link anything is visible without reading rows.
The input needs a keywords list. This one ranks seven programming languages in the United States over the last 12 months and also returns related queries:
{
"keywords": ["python", "java", "rust", "golang", "kotlin", "swift", "typescript"],
"geos": ["US"],
"timeRange": "today 12-m",
"dataTypes": ["keywordSummary", "relatedQueries"],
"maxRelatedPerKeyword": 5
}
From Python with apify-client:
from apify_client import ApifyClient
client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("datagrit/google-trends-keyword-ranker").call(run_input={
"keywords": ["python", "java", "rust", "golang", "kotlin", "swift", "typescript"],
"geos": ["US"],
"timeRange": "today 12-m",
"dataTypes": ["keywordSummary", "relatedQueries"],
"maxRelatedPerKeyword": 5,
})
rows = list(client.dataset(run["defaultDatasetId"]).iterate_items())
Or with cURL, which returns the rows directly:
curl -X POST "https://api.apify.com/v2/acts/datagrit~google-trends-keyword-ranker/run-sync-get-dataset-items?token=YOUR_APIFY_TOKEN" \
-H "Content-Type: application/json" \
-d '{"keywords":["python","rust","golang"],"geos":["US","DE"],"dataTypes":["keywordSummary"]}'
Locations are country codes such as US or DE, sub-regions such as US-CA, or WORLDWIDE. Several locations in one run give you one ranking per location, which is the quickest way to see where a keyword is strongest.
For the seven languages above the keyword summary rows came back like this:
| keyword | rank | normalizedAverage | scaleQuality |
|---|---|---|---|
| swift | 1 | 31.6 | good |
| python | 2 | 30.5 | exact |
| java | 3 | 15.1 | exact |
| rust | 4 | 15 | exact |
| typescript | 5 | 1.8 | coarse |
| golang | 6 | 1 | coarse |
| kotlin | 7 | 0.8 | coarse |
normalizedAverage is the average interest on the shared scale, where the strongest point of any keyword in the location is 100. The other fields that matter in a summary row are:
| Field | What it tells you |
|---|---|
peakValue, peakDate | The highest point on the shared scale and when it happened. |
latestValue | The last complete point, so an unfinished week does not distort it. |
changePct | Change between the first and last third of the range. |
trendDirection | rising, falling or steady, with 10 percent as the threshold. A keyword that starts from zero has no changePct but is rising. |
anchorKeyword | The keyword that linked this one to the reference group. |
A ranking is only the start of the work. Swift tops the list because the word also names a singer and a bird, which Google Trends cannot separate in a plain search. Related queries make that visible, and the category input lets you restrict a search to a Google Trends category when a word has several meanings.
Shortlist keywords in pandas. Keep the ones that are both established and growing:
import pandas as pd
df = pd.DataFrame(rows)
summary = df[(df["type"] == "keywordSummary") & (df["found"] == True)]
shortlist = summary[(summary["trendDirection"] == "rising") & (summary["scaleQuality"].isin(["exact", "good"]))]
print(shortlist.sort_values("normalizedAverage", ascending=False)[["keyword", "normalizedAverage", "changePct"]])
Spot new topics early. Ask for relatedQueryKind: "rising" and schedule the run weekly. Related query rows carry isBreakout, which is true when Google reports growth of more than 5,000 percent. Append each week's rows to a sheet and alert on new breakout queries for your seed keywords.
Compare markets. Put three countries in geos and the same keywords in keywords, then pivot normalizedAverage by geo. Because each location has its own ranking, a keyword that is 12th in one country and 2nd in another stands out immediately. For a finer split, add interestByRegion to dataTypes, and use regionResolution to switch between states, metro areas and cities.
The Actor does not return silent empty results. A keyword without enough search volume in a location, or one that rounds to 0 on every point next to much stronger keywords, gives one row with found: false and reason: "noData", and a location code Google rejects gives reason: "badLocation". A temporary failure gives reason: "fetchFailed". These status rows are not charged. When Google changes its response format so that a required part is missing, the run fails with a message that names it, instead of delivering rows full of nulls.
good placement is reliable for ordering; a coarse one is approximate; an unlinked keyword has no rank. Check scaleQuality before using small differences.noData. A rare term in the same list as a very popular one can also round to 0; run it on its own to see its curve.maxItems input stops a run at the row count you set.The method is simple enough to build yourself: read groups of five, repeat an anchor, rescale by the ratio, and keep track of how thin the anchor was. The Actor does it for lists up to 100 keywords and several countries at once. It is on the Apify Store as Google Trends Keyword Ranker and Compare Tool, and the full input and output reference is on the documentation page. It is priced per result, and a maximum spend on the run caps what a run can cost.
Find Medium publications by keyword and score each by followers, posting cadence, claps per 1,000 followers and paywalled share, in Python or cURL.
Pull Product Hunt leaderboards with each launch's real website, pricing page, plan tiers and lowest paid price, from Python or cURL.
Pull Bilibili's Top 100 anime ranking, a filterable catalog with follower and rating counts, and the release calendar as clean JSON using Python or cURL.