Skip to content

Migrating from the GDELT DOC 2.0 API ​

Replace api.gdeltproject.org/api/v2/doc/doc with /v1/news/everything. Check the differences in language coverage, search and rate limits before migrating.

These are not the same kind of product ​

GDELT is a free research dataset. APITube is a commercial news API. Choose based on the features and coverage you need.

GDELT DOC 2.0APITube
Key requiredNoYes
CostFreePaid, free tier available
Rate limitEffectively a handful per hour — see below50/minute paid, 10/minute free
Records per request250250
PagingNonepage
Search scopeFull article text, 65+ languagesHeadlines
Article bodyNot returnedbody and body_html
Fields per article8Dozens
ErrorsHTTP 200 with a plain-text bodyJSON with a status and an error code

Move to APITube for: the article text, commercial licensing, entity extraction, sentiment, and a rate limit that supports production traffic.

Keep GDELT if you need: free full-text searches in 65 languages, GKG topic categories or tone timelines. APITube does not replace this research coverage.

Your first request ​

bash
# GDELT — no key needed
curl "https://api.gdeltproject.org/api/v2/doc/doc?query=tesla&mode=artlist&format=json&maxrecords=250"
bash
# APITube
curl "https://api.apitube.io/v1/news/everything?title=tesla&per_page=250" \
  -H "X-API-Key: YOUR_API_KEY"

GDELT reports errors with HTTP 200 ​

Check the response body as well as the HTTP status. For example, request more than the maximum number of results:

bash
curl "https://api.gdeltproject.org/api/v2/doc/doc?query=tesla&mode=artlist&format=json&maxrecords=251"
# HTTP 200
# A maximum of 250 records can be returned (10 on Free, 50 on Starter, 200 on Basic).

GDELT can return HTTP 200 with a plain-text error, including for rate limits. A JSON parser will fail on these responses.

If your code treats JSON parsing failures as empty results, it may hide GDELT errors. APITube returns a structured error such as 400 ER0171, which you can handle directly.

The rate limit is the real migration cost ​

GDELT's throttle message says "one request every 5 seconds". Measured on 27 July 2026:

Interval between requestsRequests that got through
6 seconds1 of 7
16 seconds4 of 12
60 seconds3 of 8
150 seconds0 of 3
300 seconds, over 35 minutes0 of 7

Slower retries did not clear the block in this test. Roughly 60 requests over 90 minutes triggered it, and none of the retry intervals tested restored access. A pause that worked once did not work again later in the same session.

On GDELT, waiting longer between retries did not restore access during this test. APITube returns HTTP 429 when you exceed its documented per-minute limit. Wait for that limit to reset before retrying.

Request limits affect how long it takes to download past articles. Account for them when planning a migration.

Parameter mapping ​

GDELTAPITubeNote
query (bare terms)titleFull text → headlines
query domain:Xsource.domain=XExact
query sourcelang:englishlanguage.code=enName → ISO code
query sourcecountry:USsource.country.code=usName → ISO code
query theme:X—No GKG taxonomy
maxrecordsper_pageBoth cap at 250; APITube caps Free at 10, Starter at 50 and Basic at 200
mode=artlist(the default)
mode=timelinevol/v1/news/trendsDifferent endpoint and response format
mode=tonechart—Compute from sentiment.overall.score
—pageGDELT has no paging at all

The full table is in the migration kit, including the parameters it deliberately leaves unmapped because they could not be verified.

Convert language and country names to codes ​

GDELT returns language and country names in English. APITube expects ISO codes.

GDELT:    "language": "Serbian",  "sourcecountry": "Serbia"
APITube:  language.code=sr        source.country.code=rs

Forwarding the name fails, and the error tells you which mistake you made:

What you sendResponse
language.code=Serbian400 ER0061 — must be 1–2 characters
language.code=zz400 ER0237 — not found
source.country.code=Serbia400 ER0246 — must be 2 characters
source.country.code=zz400 ER0212 — not found

A length error means a GDELT value was forwarded unconverted — a bug in your mapping code. A not-found error means your table produced a code APITube does not carry — a real coverage gap. Note also that the United Kingdom is gb, not uk.

Russian and Ukrainian are absent ​

language.code=ru and =uk return 400 ER0237; source.country.code=ru returns 400 ER0212. GDELT covers both. There is no substitute and no partial coverage.

Before migrating, run your usual GDELT queries and count the rows marked "Russian". Check how much coverage your application would lose.

The language mix will shift ​

Compare language coverage with your own queries before switching. A similar total article count does not guarantee a similar mix of languages.

Check each language your application needs and compare its share of the results.

Compare article counts by language before switching.

Other migration differences to check ​

No paging on GDELT. maxrecords returns up to 250 and stops — no offset, no cursor. Queries that matched more were worked around by slicing the date range. On APITube that workaround is unnecessary: use page.

seendate is not published_at. GDELT records when it first saw the article; APITube records publication time. For a late pickup these differ, and nothing reconciles them.

Date formats differ. GDELT writes 20260709T120000Z (ISO 8601 basic); APITube's filters take 2026-07-09T12:00:00Z (extended).

Multi-value filters apply the first 3. A fourth domain or language is dropped with no error.

What you gain ​

APITube returns article text with the search results. It also includes entities with Wikidata links and sentiment scores, separate title and body sentiment, categories, topics, industries, publisher bias and rank, readability, is_duplicate, story.id and eight export formats.

Next steps ​