npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

gdelt-ts-client

v1.2.3

Published

TypeScript client for the GDELT API with full type support

Readme

GDELT TypeScript Client

A comprehensive TypeScript client for the GDELT API that provides strongly-typed access to global news data, events, and media analysis. This library supports both TypeScript and JavaScript projects with full type safety and intelligent code completion.

Features

  • Complete API Coverage: Access all GDELT API endpoints including articles, images, timelines, tone analysis, and more
  • Type Safety: Comprehensive TypeScript definitions for all parameters, responses, and configuration options
  • Query Building: Fluent API for constructing complex search queries with type safety
  • Article Content: Fetch and parse the full content of articles returned by GDELT API calls
  • Validation: Built-in parameter validation with helpful error messages
  • Retry Logic: Configurable retry mechanism for handling transient network errors
  • Response Validation: Type guards and validation for ensuring data integrity
  • Method Overloads: Simplified method signatures for common use cases
  • JavaScript Compatible: Works in both TypeScript and JavaScript environments

Installation

npm install gdelt-ts-client

Quick Start

TypeScript Example

import { GdeltClient, TimespanUnit } from 'gdelt-ts-client';

const client = new GdeltClient();

async function getRecentNews() {
  const response = await client.getArticles({
    query: 'climate change',
    timespan: '1d',
    maxrecords: 10
  });
  
  console.log(`Found ${response.count} articles`);
  response.articles.forEach(article => {
    console.log(`${article.title} (${article.domain})`);
  });
}

getRecentNews();

JavaScript Example

const { GdeltClient } = require('gdelt-ts-client');

const client = new GdeltClient();

async function getRecentNews() {
  const response = await client.getArticles({
    query: 'technology',
    timespan: '1d',
    maxrecords: 10
  });
  
  console.log(`Found ${response.count} articles`);
  response.articles.forEach(article => {
    console.log(`${article.title} (${article.domain})`);
  });
}

getRecentNews();

API Reference

Client Configuration

Create a client with optional configuration:

const client = new GdeltClient({
  timeout: 30000,        // Request timeout in milliseconds
  retry: true,           // Enable retry on failures
  maxRetries: 3,         // Maximum number of retries
  retryDelay: 1000,      // Delay between retries in milliseconds
  defaultFormat: 'json'  // Default response format
});

Core Methods

8

Article Search

Get articles matching your query:

// Simple query
const articles = await client.getArticles('climate change');

// With options
const articles = await client.getArticles('climate change', {
  timespan: '1w',
  maxrecords: 50
});

// Full parameter object
const articles = await client.getArticles({
  query: 'climate change',
  timespan: '1w',
  maxrecords: 50,
  sort: 'datedesc'
});

Image Search

Find images related to your query:

// Simple image search
const images = await client.getImages('natural disasters');

// With filtering
const images = await client.getImages('natural disasters', {
  timespan: '1d',
  maxrecords: 20
});

Timeline Analysis

Get timeline data for coverage volume:

// Simple timeline
const timeline = await client.getTimeline('covid-19', '1m');

// With smoothing
const timeline = await client.getTimeline('covid-19', {
  timespan: '1m',
  timelinesmooth: 7
});

Tone Analysis

Analyze emotional tone of coverage:

const toneChart = await client.getToneChart('election 2024');

// Process tone distribution
toneChart.tonechart.forEach(bin => {
  console.log(`Tone ${bin.bin}: ${bin.count} articles`);
});

Enhanced Query Building

Use the fluent query builder for complex searches:

// Create a complex query
const query = client.query()
  .phrase('climate change')
  .fromCountry('us')
  .withPositiveTone(3)
  .not('opinion')
  .build();

const articles = await client.getArticles(query);

Advanced Query Builder Capabilities

The query builder provides a comprehensive set of methods for constructing complex queries:

// Basic query operations
const query = client.query()
  .search('climate')                                // Simple search term
  .phrase('global warming')                         // Exact phrase match
  .anyOf('policy', 'agreement', 'treaty')           // Match any of these terms
  .allOf('emissions', 'reduction', 'targets')       // Match all of these terms
  .not('opinion')                                   // Exclude this term
  .build();

// Source filtering
const sourceQuery = client.query()
  .phrase('artificial intelligence')
  .fromDomain('techcrunch.com', true)               // Exact domain match
  .fromCountry('US')                                // Filter by country
  .inLanguage('english')                            // Filter by language
  .build();

// Tone analysis
const toneQuery = client.query()
  .phrase('economic outlook')
  .withTone('>', 5)                                 // Articles with positive tone
  .withAbsoluteTone('>', 7)                         // High emotional content
  .withPositiveTone(3)                              // Alternative for positive tone
  .withNegativeTone(-3)                             // Articles with negative tone
  .withNeutralTone(1)                               // Articles with neutral tone
  .withHighEmotion(5)                               // Articles with high emotional content
  .build();

// Content filtering
const themeQuery = client.query()
  .phrase('climate change')
  .withTheme('ENV_CLIMATE')                         // Filter by GDELT theme
  .build();

// Image-specific queries
const imageQuery = client.query()
  .phrase('natural disaster')
  .withImageTag('flood')                            // Filter by image tag
  .withImageWebTag('emergency')                     // Filter by web image tag
  .withImageOCR('rescue')                           // Filter by text in image
  .withImageFaceCount('>', 3)                       // Images with more than 3 faces
  .withImageFaceTone('<', 0)                        // Images with negative face expressions
  .withImageWebCount('>', 10)                       // Images with high web presence
  .withNovelImages(0.7)                             // Filter for novel images
  .withPopularImages(0.8)                           // Filter for popular images
  .build();

// Advanced text operations
const textQuery = client.query()
  .withProximity(5, ['climate', 'action'])          // Terms within 5 words of each other
  .withRepeat(3, 'urgent')                          // Term appears at least 3 times
  .build();

// Custom query components
const customQuery = client.query()
  .custom('domain:nytimes.com OR domain:washingtonpost.com')  // Custom query string
  .build();

// Grouping for complex logic
const groupedQuery = client.query()
  .phrase('climate change')
  .group()                                          // Group the previous terms
  .anyOf('policy', 'legislation', 'regulation')     // Match any of these terms
  .build();

Article-specific Query Builder

The specialized ArticleQueryBuilder provides methods tailored for article searches:

const articleQuery = client.articleQuery()
  .breakingNews()                                   // Filter for breaking news
  .opinions()                                       // Filter for opinion pieces
  .localNews('New York')                            // Filter for local news
  .fromDomain('cnn.com')
  .withPositiveTone(2)
  .build();

const articles = await client.getArticles(articleQuery);

Image-specific Query Builder

The specialized ImageQueryBuilder provides methods tailored for image searches:

const imageQuery = client.imageQuery()
  .disasters()                                      // Filter for disaster images
  .politicalEvents()                                // Filter for political events
  .medicalContent()                                 // Filter for medical content
  .positiveImages()                                 // Filter for positive images
  .negativeImages()                                 // Filter for negative images
  .withNovelImages()
  .build();

const images = await client.getImages(imageQuery);

Query Validation and Optimization

The client provides methods to validate and optimize queries:

// Validate a query before execution
const validation = client.validateQuery('climate change AND (weather OR temperature)');

if (!validation.valid) {
  console.error('Query errors:', validation.errors);
}

// Check query complexity
const complexity = client.getQueryComplexity('climate change AND (weather OR temperature)');
console.log(`Query complexity: ${complexity}`);

// Check for balanced parentheses and quotes
const balanced = client.hasBalancedQuotes('climate "change');
console.log(`Query has balanced quotes: ${balanced}`);

// Get optimization suggestions
const suggestions = client.getQueryOptimizations('very complex query here');
suggestions.forEach(suggestion => {
  console.log('Suggestion:', suggestion);
});

Available Methods

| Method | Description | |--------|-------------| | getArticles() | Search for news articles | | getArticlesWithContent() | Search for news articles and fetch their full content | | fetchContentForArticles() | Fetch full content for existing articles | | getImages() | Search for images and photos | | getTimeline() | Get timeline of coverage volume | | getTimelineWithArticles() | Get timeline with article details | | getTimelineByLanguage() | Get timeline broken down by language | | getTimelineByCountry() | Get timeline broken down by country | | getTimelineTone() | Get timeline of average tone | | getToneChart() | Get tone distribution chart | | getImageTagCloud() | Get word cloud of image tags | | getImageWebTagCloud() | Get word cloud of web image tags |

Query Parameters

All methods support these parameters:

| Parameter | Type | Description | |-----------|------|-------------| | query | string | Search query (required) | | timespan | string | Time period (e.g., '1d', '1w', '1m') | | startdatetime | string | Start date (YYYYMMDDHHMMSS format) | | enddatetime | string | End date (YYYYMMDDHHMMSS format) | | maxrecords | number | Maximum results (1-250, default 75) | | sort | string | Sort order ('datedesc', 'dateasc', 'tonedesc', 'toneasc') | | timelinesmooth | number | Timeline smoothing (1-30) | | format | string | Response format ('json', 'csv', 'html') |

Query Operators

Build powerful queries using GDELT operators:

// Domain filtering
const query = 'climate change domain:cnn.com';

// Country filtering
const query = 'elections sourcecountry:unitedstates';

// Language filtering
const query = 'brexit sourcelang:english';

// Tone filtering
const query = 'economy tone>5';  // Positive tone articles

// Theme filtering
const query = 'theme:ENV_CLIMATE';

// Image filtering
const query = 'imagetag:"flood"';

// Complex combinations
const query = 'climate change AND sourcecountry:germany AND tone>2';

Error Handling

The client provides comprehensive error handling:

try {
  const response = await client.getArticles({
    query: 'climate change',
    maxrecords: 300  // Invalid: exceeds 250 limit
  });
} catch (error) {
  if (error instanceof Error) {
    console.error('Error:', error.message);
    // Handle specific error types
  }
}

Type Safety

Take advantage of full TypeScript support:

import { 
  GdeltClient, 
  IArticleListResponse, 
  IImageCollageResponse,
  TimespanUnit,
  Mode,
  Format
} from 'gdelt-ts-client';

// Strongly typed responses
const articles: IArticleListResponse = await client.getArticles('query');
const images: IImageCollageResponse = await client.getImages('query');

// Type-safe constants
const timespan = client.createTimespan(1, TimespanUnit.DAYS);

Advanced Usage

Custom Configuration

const client = new GdeltClient({
  timeout: 60000,
  retry: true,
  maxRetries: 5,
  retryDelay: 2000,
  defaultFormat: Format.JSON
});

Complex Query Building

const complexQuery = client.query()
  .phrase('artificial intelligence')
  .anyOf('machine learning', 'deep learning', 'neural networks')
  .fromCountry('us')
  .withTheme('SCI_TECH')
  .withPositiveTone(3)
  .not('opinion')
  .group()
  .build();

const response = await client.getArticles(complexQuery, {
  timespan: '1w',
  maxrecords: 100,
  sort: 'datedesc'
});

Response Processing

const response = await client.getArticles('climate change');

// Process articles with null safety
response.articles.forEach(article => {
  if (article.title && article.url) {
    console.log(`${article.title}`);
    console.log(`URL: ${article.url}`);
    console.log(`Tone: ${article.tone?.toFixed(2) ?? 'N/A'}`);
    console.log(`Date: ${article.seendate}`);
  }
});

Article Content Fetching

The client provides methods to fetch and parse the full content of articles returned by GDELT API calls:

import { GdeltClient } from 'gdelt-ts-client';

const client = new GdeltClient({
  contentFetcher: {
    concurrencyLimit: 3,        // Maximum number of concurrent requests
    requestDelay: 1500,         // Delay between requests to the same domain (ms)
    userAgent: 'MyApp/1.0.0',   // Custom user agent
    respectRobotsTxt: true      // Whether to respect robots.txt
  }
});

// Fetch articles with content in one call
const articlesWithContent = await client.getArticlesWithContent({
  query: 'climate change',
  timespan: '1d',
  maxrecords: 10
});

console.log(`Fetched ${articlesWithContent.contentStats.successCount} articles with content`);

articlesWithContent.articles.forEach(article => {
  if (article.content) {
    console.log(`Title: ${article.title}`);
    console.log(`Word Count: ${article.content.wordCount}`);
    console.log(`Content Preview: ${article.content.text.substring(0, 200)}...`);
  }
});

Fetching Content for Existing Articles

You can also fetch content for articles you've already retrieved:

// Get articles first
const articles = await client.getArticles({
  query: 'technology news',
  timespan: '2h',
  maxrecords: 20
});

// Then selectively fetch content
const articlesWithContent = await client.fetchContentForArticles(
  articles.articles,
  {
    allowedDomains: ['bbc.com', 'reuters.com', 'apnews.com'],  // Only fetch from these domains
    concurrencyLimit: 2,                                       // Limit concurrent requests
    onProgress: (completed, total) => {                        // Track progress
      console.log(`Progress: ${completed}/${total} articles processed`);
    },
    includeFailures: true,      // Include articles where content fetching failed
    parseContent: true,         // Parse and clean the content
    includeRawHTML: false       // Don't include raw HTML in the response
  }
);

// Filter successful content fetches
const successfulArticles = articlesWithContent.filter(
  article => article.contentResult.success
);

console.log(`Successfully fetched content for ${successfulArticles.length} articles`);

Content Fetching Configuration

The content fetcher can be configured with various options:

const client = new GdeltClient({
  contentFetcher: {
    // Request control
    concurrencyLimit: 5,        // Maximum concurrent requests
    requestDelay: 1000,         // Delay between requests to same domain (ms)
    timeout: 10000,             // Request timeout (ms)
    maxRetries: 2,              // Maximum retries per request
    
    // Rate limiting
    maxRequestsPerSecond: 1,    // Maximum requests per second per domain
    maxRequestsPerMinute: 30,   // Maximum requests per minute per domain
    
    // Ethical scraping
    respectRobotsTxt: true,     // Respect robots.txt files
    userAgent: 'MyApp/1.0.0',   // User agent string
    
    // Domain filtering
    skipDomains: ['paywall.com', 'subscription-only.com'],  // Skip these domains
    
    // Request behavior
    followRedirects: true,      // Follow redirects
    maxRedirects: 5,            // Maximum redirects to follow
    customHeaders: {            // Custom headers for requests
      'Accept-Language': 'en-US,en;q=0.9'
    }
  }
});

Content Fetching Statistics

You can access statistics about the content fetching process:

const result = await client.getArticlesWithContent({
  query: 'breaking news',
  timespan: '1h',
  maxrecords: 50
});

// Check content fetching statistics
console.log('Content Fetching Statistics:');
console.log(`Success Rate: ${(result.contentStats.successCount / result.count * 100).toFixed(1)}%`);
console.log(`Average Fetch Time: ${result.contentStats.averageFetchTime}ms`);
console.log(`Total Time: ${result.contentStats.totalFetchTime}ms`);

// Log failure reasons
Object.entries(result.contentStats.failureReasons).forEach(([reason, count]) => {
  console.log(`${reason}: ${count} failures`);
});

Timeline Analysis

const timeline = await client.getTimeline('covid-19', '1m');

if (timeline.timeline && timeline.timeline.length > 0) {
  timeline.timeline.forEach(point => {
    if (point && point.date && typeof point.value === 'number') {
      console.log(`${point.date}: ${point.value.toFixed(4)}%`);
    }
  });
}

Examples

Basic News Search

import { GdeltClient } from 'gdelt-ts-client';

const client = new GdeltClient();

async function searchNews() {
  const articles = await client.getArticles({
    query: 'renewable energy',
    timespan: '1d',
    maxrecords: 20
  });
  
  console.log(`Found ${articles.count} articles about renewable energy`);
  
  articles.articles.forEach((article, index) => {
    console.log(`${index + 1}. ${article.title}`);
    console.log(`   Source: ${article.domain}`);
    console.log(`   Date: ${article.seendate}`);
    console.log(`   Tone: ${article.tone?.toFixed(2) ?? 'N/A'}`);
  });
}

searchNews();

Image Analysis

async function analyzeImages() {
  const images = await client.getImages({
    query: 'imagetag:"protest"',
    timespan: '1w',
    maxrecords: 10
  });
  
  console.log(`Found ${images.count} protest images`);
  
  images.images.forEach((image, index) => {
    console.log(`${index + 1}. ${image.url}`);
    console.log(`   Article: ${image.articleurl}`);
    console.log(`   Tags: ${image.tags?.join(', ') ?? 'None'}`);
  });
}

Tone Distribution Analysis

async function analyzeTone() {
  const toneChart = await client.getToneChart({
    query: 'cryptocurrency',
    timespan: '1w'
  });
  
  console.log('Tone distribution for cryptocurrency coverage:');
  
  const totalArticles = toneChart.tonechart.reduce((sum, bin) => sum + bin.count, 0);
  
  toneChart.tonechart.forEach(bin => {
    const percentage = (bin.count / totalArticles * 100).toFixed(1);
    console.log(`Tone ${bin.bin}: ${bin.count} articles (${percentage}%)`);
  });
}

Requirements

  • Node.js >= 18.0.0
  • TypeScript >= 5.0.0 (for TypeScript projects)

License

MIT License - see LICENSE file for details.

Contributing

Contributions are welcome. Please ensure all tests pass and maintain code coverage above 90%.

Support

For bug reports and feature requests, please use the GitHub issues page.