semust logo

API Platform

Trends API

Google Trends data for up to five keywords — interest over time, by region, related searches — plus age and gender demographics, at a flat price per request.

Find out how search interest in up to five keywords moves over time, where it comes from, what people search alongside it and who searches. One endpoint serves four reports, selected with the type parameter. Interest, regions and related searches are Google Trends data; demographics are a clickstream-based estimate, because Google Trends has none.

Requests longer than 60 seconds

This endpoint runs requests as tasks. A request that runs longer than 60 seconds returns 202 with a task_id; collect the result from GET /v1/tasks/{task_id}. Every response, including a normal 200, carries the task id in the X-Task-Id header. Use ?wait= to change how long the request waits, and an Idempotency-Key header to retry safely.

Authentication

HeaderTypeDescription
SEMUST-API-USERstringYour API user's username
SEMUST-API-PASSWORDstringYour API user's password
Accept-LanguagestringOptional. Send tr to receive error messages in Turkish

Create API credentials from the API Access page.

SEMUST-API-USER: your_username
SEMUST-API-PASSWORD: your_password
Content-Type: application/json

Report Types

typeReturnsKeywordsPrice
interest (default)Interest over time, one point per interval, plus each keyword's average1–5$0.0121
regionsInterest by region (provinces for Turkey), and how the keywords split each region1–5$0.0121
relatedTop and rising related searches and related topics1$0.0121
demographicsInterest by age group and gender1–5$0.00264

The price is per request: comparing five keywords costs the same as one, whatever the period or search type.

{
  "keywords": ["iphone 17", "samsung s26"],
  "period": "past_12_months"
}

Request Parameters

A parameter that does not apply to the chosen type is rejected rather than ignored, and a misspelled one is named in the error with a suggestion. A JSON null is treated as "not sent".

Body

typestringdefault: interest

interest, regions, related or demographics.

keywordsstring[]

Required. 1–5 keywords to compare (related: exactly one). Each up to 100 characters, without commas. Repeats that differ only in case are dropped, and the first spelling is kept.

countrystringdefault: TR

Two-letter country code. See Markets below.

languagestring

Not for demographics. The language of region names and related topics. Defaults to tr for TR and en elsewhere. It does not change which searches are counted.

periodstringdefault: past_12_months

past_day, past_7_days, past_30_days, past_90_days, past_12_months or past_5_years.

search_typestringdefault: web

Not for demographics. Where searches are counted: web, news, images, youtube or shopping.

idempotency_keystring

Optional, up to 128 characters. Repeating a request with the same key returns the same task — its 202 while it runs, its stored result once it finishes — and it is charged once. The key is reserved until 72 hours after the task finishes. Same as the Idempotency-Key header; if you send both, this field wins.

Query

waitintegerdefault: 60

Seconds to wait for the result, 0–80. If the request is still running after that, the response is 202 with a task_id. 0 answers 202 at once.

Headers

Idempotency-Keystring

Optional. Works like idempotency_key above; if you send both, the body field wins.

GET /v1/trends/markets lists every supported country and language. It is free.

A request still running after 60 seconds returns 202. The call() helper on Tasks & Long-Running Requests polls until the result is ready.

curl -X POST https://data.semust.com/v1/trends \
  -H "SEMUST-API-USER: your_username" \
  -H "SEMUST-API-PASSWORD: your_password" \
  -H "Content-Type: application/json" \
  -d '{"keywords": ["iphone 17", "samsung s26"], "period": "past_90_days"}'

Response

interest, regions and demographics return rows in items; related returns one data object. Every per-keyword list — values, averages, interest, share — is in the same order as keywords in the envelope, so you can read it by position.

Interest is relative, not a search count. In interest, 100 is the highest point of any keyword in the period, so the keywords can be compared directly. In regions, interest puts each keyword on its own scale (100 is that keyword's strongest region) and share says how the keywords split a region's searches, in percent. Demographic values are 0–100 against the keyword's largest group.

A keyword with no data is a valid answer: items is empty and values are null. It is billed like any other request.

The examples below are real responses.

{
  "success": true,
  "type": "interest",
  "keywords": ["iphone 17", "samsung s26"],
  "country": "TR",
  "language": "tr",
  "period": "past_12_months",
  "search_type": "web",
  "averages": [56, 7],
  "count": 53,
  "items": [
    { "time": "2025-11-02T00:00:00Z", "values": [57, 2], "partial": false },
    { "time": "2025-11-09T00:00:00Z", "values": [60, 2], "partial": false },
    { "time": "2026-11-01T00:00:00Z", "values": [46, 9], "partial": true }
  ],
  "cost": 0.0121,
  "cached": false,
  "request_id": "0b7e6f1a-3c2d-4e5f-9a8b-1c2d3e4f5a6b"
}

Response Fields Reference

Envelope

FieldTypeDescription
keywordsstring[]The keywords as run, after duplicates were removed. Every per-keyword list follows this order
averages(integer | null)[]interest only. Each keyword's average over the period
countintegerRows in items

interest row

FieldTypeDescription
timestringStart of the interval, ISO 8601 in UTC. The interval follows the period: minutes for past_day, hours for past_7_days, days or weeks for the longer periods (weeks for past_12_months)
values(integer | null)[]Interest per keyword, 0–100
partialbooleantrue for an interval still in progress; its value will change

regions row

FieldTypeDescription
region, region_codestring, string | nullRegion name in language, and its ISO 3166-2 code (TR-34)
interest(integer | null)[]Each keyword's interest here, 0–100 on its own scale
share(integer | null)[] | nullHow the keywords split this region's searches, in percent. null for a single keyword

Rows are sorted by the first keyword's interest, highest first.

top_queries and rising_queries are {query, value}; top_topics and rising_topics are {topic, category, value}, where category is the kind of topic in language. In the top lists value is relative interest, 0–100. In the rising lists it is growth over the previous period, in percent.

demographics row

keyword, age and gender, each a list of {group, value}. A keyword without data has empty lists.

Errors

Every error carries a stable code, a readable error, and retryable; where it helps also field, hint and allowed. Send Accept-Language: tr for Turkish messages. You are never charged for an error. The full list, shared with the other APIs, is on Error Codes. Specific to this endpoint:

StatusCodeMeaningWhat to do
202—Not an error: still running after wait secondsPoll GET /v1/tasks/{task_id}; see Tasks
400KEYWORDS_REQUIREDNo keywords, or an empty listSend 1–5 keywords
400TOO_MANY_KEYWORDSMore than 5 keywords, or more than one for relatedSplit the request
400INVALID_PARAMETERe.g. a keyword over 100 characters or with a comma, or an unknown period; field names it and allowed lists the valuesFix the field
400UNSUPPORTED_MARKETUnknown country or languageGET /v1/trends/markets
{
  "error": "type=related accepts at most 1 keyword(s)",
  "code": "TOO_MANY_KEYWORDS",
  "field": "keywords",
  "hint": "interest, regions and demographics compare up to 5 keywords; related takes one keyword per request",
  "retryable": false
}

Credits & Limits

RequestCost
interest, regions or related$0.0121
demographics$0.00264

The price does not depend on the number of keywords, the period or the search type. An answer with no data is billed at the same price.

Results are cached — 1 hour for past_day, 6 hours for past_7_days, 24 hours for the longer periods. A cached answer is marked "cached": true and billed at the same price as a live one.

Per-minute and per-day limits are set on your account (429 RATE_LIMIT_EXCEEDED). At most 5 requests per API user run at the same time; more get 429 TOO_MANY_CONCURRENT_REQUESTS with Retry-After. A request that has returned 202 keeps its place until its task finishes. At most 100 tasks per API user can be unfinished at once (429 TOO_MANY_PENDING_TASKS). Polling has its own limit and does not count against any of these; see Tasks.

Last updated: 2026-11-07