no key · no human
HomeAPI documentationGET /v1/search

GET /v1/search

Full-text search across the corpus, with filters. All parameters are optional — a bare call returns the newest articles in the index.

bash
curl "https://freenewsapi.ai/v1/search?q=merger&country=DE&date=48h&sort=date&size=20"

Query

qstring

The search phrase. Matched against title (weight 3), description (weight 2) and the article body. All terms must be present (AND semantics), so adding a word narrows the result rather than widening it.

Maximum 500 characters. Omit it entirely to browse by filter alone.

?q=central+bank+rate

Filters

Filters combine with AND across parameters and OR within a parameter. Asking for country=DE,AT&lang=de means “German-language articles from Germany or Austria”.

countryCSV, ISO 3166-1 alpha-2

Publisher country, uppercase. Up to 50 values.

?country=UA · ?country=DE,AT,CH

Country is derived, not declared — see country_source in response fields and the caveat under strict_country below.

langCSV, ISO 639-1

Article language, lowercase. Detected from the document, 99.9% coverage.

?lang=ru · ?lang=es,pt

tldCSV

Top-level domain of the publisher, without the dot. Useful when you care about the domain zone rather than the inferred country — tld=ua is a fact, country=UA is an inference.

?tld=ua · ?tld=ru,by,kz

hostCSV

Exact hostnames, lowercase, as they appear in the article URL. Include the www. prefix if the publisher uses one.

?host=www.reuters.com,apnews.com

Time

dateenum

Preset period, evaluated against published_at. One of:

today · yesterday · 24h · 48h · 7d · 30d

today and yesterday snap to calendar day boundaries in UTC; 24h and 48h are rolling windows from the current moment.

Cheaper than an equivalent from/to pair, because the preset maps onto a rounded range the search engine can cache.

fromdate or expression

Start of the range, inclusive. Either YYYY-MM-DD, a full timestamp YYYY-MM-DDTHH:MM:SSZ, or a relative expression such as now-7d or now-12h.

?from=2026-08-10 · ?from=now-36h

todate or expression

End of the range, exclusive. Same formats as from. Passing from=2026-08-10&to=2026-08-11 returns exactly one calendar day.

The index holds a rolling 30-day window. A from older than that is not an error — it simply returns nothing before the retention boundary. Check /stats for the oldest day currently held.

Ordering and paging

sortenumdefault date

One of:

  • date — newest publication first. The default.
  • date_asc — oldest first.
  • crawled — most recently ingested first. Use this to poll for new arrivals: publication time can be backdated by the publisher, crawl time cannot.
  • crawled_asc — oldest ingest first.
  • relevance — best textual match first. Only meaningful with q.
sizeinteger 1–100default 20

Results per page.

offsetinteger 0–9900default 0

How many results to skip. The ceiling of 9,900 is a hard limit of the underlying engine, not a policy. To walk past it, slice by time instead — see pagination.

Response shaping

full_textbooleandefault false

Include the article body in the text field. Off by default because bodies dominate response size: a 20-result page grows from roughly 12 KB to 90 KB.

highlightbooleandefault false

Add a highlight object with matched fragments wrapped in <em>. Requires q. Returns up to two 200-character fragments from the body plus any matches in title and description.

strict_countrybooleandefault false

Drop articles whose country was inferred from an en-US locale tag.

Why this exists: a large share of Indian, Nigerian and Filipino publishers ship <html lang="en-US"> as a template default. Taken at face value that inflates the United States and hides those countries. When you are counting by country rather than reading articles, set this to true and accept a smaller, cleaner sample.

Every article tells you which it is via country_source.

Response

json
{
  "took_ms": 41,
  "total": 1284,
  "total_is_lower_bound": false,
  "size": 20,
  "offset": 0,
  "results": [ ... ]
}

total is capped at 10,000 for speed. When the true count is higher, total_is_lower_bound becomes true and total reads exactly 10000. For an exact count of a large slice, use /v1/stats, which always counts precisely.

Article fields are documented in response fields.

Worked examples

Everything published today in Ukraine

bash
curl "https://freenewsapi.ai/v1/search?country=UA&date=today&sort=date&size=50"

Poll for new arrivals every ten minutes

bash
curl "https://freenewsapi.ai/v1/search?q=opec&sort=crawled&from=now-10m&size=100"

One publisher, one calendar day

bash
curl "https://freenewsapi.ai/v1/search?host=www.reuters.com&from=2026-08-15&to=2026-08-16&size=100"

Relevance search with highlights, English only

bash
curl "https://freenewsapi.ai/v1/search?q=supply+chain+disruption&lang=en&sort=relevance&highlight=true"

Clean country analytics

bash
curl "https://freenewsapi.ai/v1/search?country=IN&strict_country=true&date=7d&size=100"