You're Invited:Meet the Socket Team at BlackHat and DEF CON in Las Vegas, Aug 4-6.RSVP
Socket
Book a DemoInstallSign in
Socket

AsyncDDGS

Package Overview
Dependencies
Maintainers
1
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

AsyncDDGS

Asynchronous DuckDuckGo Search API: A FastAPI service for async access to DuckDuckGo’s text, image, video, and news searches. Uses a custom aDDGS class with aiohttp and asyncio for concurrent queries. Supports advanced syntax and proxies.

0.1.0a1
pipPyPI
Maintainers
1

Async DuckDuckGo Search API

Build Status PyPI version

This FastAPI-based application provides a standalone interface to DuckDuckGo's core search functionalities, including text search, image search, video search, and news search. It uses asynchronous programming to efficiently query DuckDuckGo's search engine, offering a robust and scalable solution. The API is built on top of the aDDGS class from the asyncddgs module, which handles the asynchronous interactions with DuckDuckGo and can also be used directly in Python code for custom applications.

Note: This API is not affiliated with DuckDuckGo and is intended for educational purposes only. Users must comply with DuckDuckGo's Terms of Service when utilizing this API.

Table of Contents

Installation

The asyncddgs module is published on PyPI and can be installed using pip. Python 3.9 or higher is required.

To install the module:

pip install asyncddgs

This command installs the asyncddgs module and its core dependencies, including aiohttp, lxml, and others necessary for the aDDGS class to function.

If you plan to run the FastAPI application, additional dependencies are required:

pip install fastapi uvicorn
  • fastapi: High-performance web framework for the API.
  • uvicorn: ASGI server to run FastAPI.

Alternatively, you can use the aDDGS class directly in your asynchronous Python code without the FastAPI app, requiring only the base asyncddgs installation.

Verify Installation:

pip list

Confirm that asyncddgs, and optionally fastapi and uvicorn, are installed.

Using the aDDGS Class

The aDDGS class is the core of the asyncddgs module, providing asynchronous methods to perform searches on DuckDuckGo. It leverages aiohttp for HTTP requests and includes features like rate limiting, proxy support, and customizable headers, making it suitable for both standalone use and integration into applications like the FastAPI app.

Initialization and Configuration

The aDDGS class is initialized with parameters that configure its behavior:

from asyncddgs import aDDGS

async with aDDGS(
    headers=None,
    proxy=None,
    timeout=10,
    verify=True,
    enable_rate_limit=True,
    min_request_interval=20.0,
    delay_if_needed=0.75
) as ddgs:
    # Use the instance here
    pass

Parameters:

  • headers: dict[str, str] | None
    Custom headers for HTTP requests (e.g., {"Accept": "application/json"}). Defaults to a predefined User-Agent mimicking Chrome 100 if not specified.

  • proxy: str | None
    Proxy URL (e.g., "http://user:pass@example.com:3128") for routing requests. Supports HTTP, HTTPS, and SOCKS5. Overrides the aDDGS_PROXY environment variable if set. Defaults to None.

  • timeout: int | None
    Total timeout in seconds for each HTTP request (connection and read). Defaults to 10 seconds.

  • verify: bool
    Whether to verify SSL certificates. Set to False for self-signed certificates or certain proxies (reduces security). Defaults to True.

  • enable_rate_limit: bool
    Enables rate limiting to avoid exceeding DuckDuckGo's request limits. Defaults to True.

  • min_request_interval: float
    Minimum interval in seconds between requests when rate limiting is enabled. Defaults to 20.0 seconds.

  • delay_if_needed: float
    Delay in seconds to sleep if the time since the last request is less than min_request_interval. Defaults to 0.75 seconds.

These parameters allow customization for specific use cases, such as adjusting request rates or routing through proxies.

Configuration Options

The initialization parameters provide fine-grained control over the aDDGS instance:

  • Headers: Customize the User-Agent or add metadata to mimic browsers or pass additional information.
  • Proxy: Use HTTP, HTTPS, or SOCKS5 proxies for anonymity or to bypass restrictions. Example: "socks5://user:pass@example.com:1080".
  • Timeout: Adjust based on network conditions or expected response times.
  • SSL Verification: Disable for testing with self-signed certificates, but use cautiously due to security risks.
  • Rate Limiting: Toggle or adjust enable_rate_limit, min_request_interval, and delay_if_needed to balance speed and compliance with DuckDuckGo's policies.

Internal Methods

The class includes internal methods that support its functionality:

  • _sleep:
    Manages rate limiting by sleeping asynchronously if requests are made too quickly, based on min_request_interval and delay_if_needed.

  • _get_url:
    A generic method to make HTTP requests (GET, POST, etc.) with customizable parameters (e.g., headers, data, proxy). Returns an aiohttp.ClientResponse object.

  • _get_vqd:
    Extracts the 'vqd' token required for image, video, and news searches by querying DuckDuckGo with the search keywords.

These methods are used internally by the search methods but are critical to understanding the class's operation.

Search Methods

The aDDGS class provides four primary asynchronous search methods:

The text method performs a text search on DuckDuckGo, returning web page titles, URLs, and snippets.

async def text(
    keywords: str,
    region: str = "wt-wt",
    safesearch: str = "moderate",
    timelimit: str | None = None,
    backend: str = "auto",
    max_results: int | None = None,
    max_pages: int = 5
) -> list[dict[str, str]]
ParameterTypeDescriptionPossible ValuesDefault
keywordsstrSearch query (required).Any string (e.g., "python", "site:python.org")Required
regionstrRegion code for localized results."wt-wt" (worldwide), "us-en", "uk-en", "de-de", etc."wt-wt"
safesearchstrFilters explicit content."on", "moderate", "off""moderate"
timelimitstr | NoneLimits results by publication time."d" (day), "w" (week), "m" (month), "y" (year)None
backendstrSpecifies the DuckDuckGo backend to use."auto" (randomly selects "html" or "lite"), "html", "lite""auto"
max_resultsint | NoneMaximum number of results to return.Any positive integer (e.g., 10)None (first page)
max_pagesintMaximum number of result pages to fetch.Any positive integer (e.g., 5)5
  • Returns: List of dictionaries with title, href, and body.

  • Behavior: Supports two backends ("html" and "lite") for parsing results, with pagination and deduplication.

Usage Example
import asyncio
from asyncddgs import aDDGS

async def main():
    async with aDDGS() as ddgs:
        # Search for "python programming" with specific parameters
        text_results = await ddgs.text(
            keywords="python programming",
            region="us-en",
            safesearch="off",
            timelimit="m",
            backend="html",
            max_results=5,
            max_pages=3
        )
        for result in text_results:
            print(f"Title: {result['title']}")
            print(f"URL: {result['href']}")
            print(f"Snippet: {result['body']}\n")

if __name__ == "__main__":
    asyncio.run(main())

The images method searches for images with extensive filtering options.

async def images(
    keywords: str,
    region: str = "wt-wt",
    safesearch: str = "moderate",
    timelimit: str | None = None,
    size: str | None = None,
    color: str | None = None,
    type_image: str | None = None,
    layout: str | None = None,
    license_image: str | None = None,
    max_results: int | None = None,
    max_pages: int = 5
) -> list[dict[str, str]]
ParameterTypeDescriptionPossible ValuesDefault
keywordsstrSearch query (required).Any string (e.g., "sunset")Required
regionstrRegion code for localized results."wt-wt", "us-en", "uk-en", etc."wt-wt"
safesearchstrFilters explicit content."on", "moderate", "off""moderate"
timelimitstr | NoneLimits results by time."Day", "Week", "Month", "Year"None
sizestr | NoneFilters by image size."Small", "Medium", "Large", "Wallpaper"None
colorstr | NoneFilters by image color."color", "Monochrome", "Red", "Orange", "Yellow", "Green", "Blue", "Purple", "Pink", "Brown", "Black", "Gray", "Teal", "White"None
type_imagestr | NoneFilters by image type."photo", "clipart", "gif", "transparent", "line"None
layoutstr | NoneFilters by image layout."Square", "Tall", "Wide"None
license_imagestr | NoneFilters by image license."any", "Public", "Share", "ShareCommercially", "Modify", "ModifyCommercially"None
max_resultsint | NoneMaximum number of results.Any positive integer (e.g., 10)None
max_pagesintMaximum pages to fetch.Any positive integer (e.g., 5)5
  • Returns: List of dictionaries with title, image, thumbnail, url, height, width, and source.
Usage Example
import asyncio
from asyncddgs import aDDGS

async def main():
    async with aDDGS() as ddgs:
        # Search for "sunset" images with filters
        image_results = await ddgs.images(
            keywords="sunset",
            region="wt-wt",
            safesearch="moderate",
            timelimit="Week",
            size="Large",
            color="Orange",
            type_image="photo",
            layout="Wide",
            license_image="Share",
            max_results=4,
            max_pages=2
        )
        for result in image_results:
            print(f"Title: {result['title']}")
            print(f"Image URL: {result['image']}")
            print(f"Thumbnail: {result['thumbnail']}")
            print(f"Source: {result['source']}\n")

if __name__ == "__main__":
    asyncio.run(main())

The videos method searches for videos with filters for resolution and duration.

async def videos(
    keywords: str,
    region: str = "wt-wt",
    safesearch: str = "moderate",
    timelimit: str | None = None,
    resolution: str | None = None,
    duration: str | None = None,
    license_videos: str | None = None,
    max_results: int | None = None,
    max_pages: int = 8
) -> list[dict[str, str]]
ParameterTypeDescriptionPossible ValuesDefault
keywordsstrSearch query (required).Any string (e.g., "python tutorials")Required
regionstrRegion code for localized results."wt-wt", "us-en", "uk-en", etc."wt-wt"
safesearchstrFilters explicit content."on", "moderate", "off""moderate"
timelimitstr | NoneLimits results by time."d" (day), "w" (week), "m" (month)None
resolutionstr | NoneFilters by video resolution."high", "standard"None
durationstr | NoneFilters by video duration."short", "medium", "long"None
license_videosstr | NoneFilters by video license."creativeCommon", "youtube"None
max_resultsint | NoneMaximum number of results.Any positive integer (e.g., 5)None
max_pagesintMaximum pages to fetch.Any positive integer (e.g., 8)8
  • Returns: List of dictionaries with content (video URL), title, and additional fields.
Usage Example
import asyncio
from asyncddgs import aDDGS

async def main():
    async with aDDGS() as ddgs:
        # Search for "python tutorials" videos with filters
        video_results = await ddgs.videos(
            keywords="python tutorials",
            region="uk-en",
            safesearch="on",
            timelimit="w",
            resolution="high",
            duration="medium",
            license_videos="youtube",
            max_results=3,
            max_pages=4
        )
        for result in video_results:
            print(f"Title: {result['title']}")
            print(f"Video URL: {result['content']}\n")

if __name__ == "__main__":
    asyncio.run(main())

The news method fetches news articles with filters for recency.

async def news(
    keywords: str,
    region: str = "wt-wt",
    safesearch: str = "moderate",
    timelimit: str | None = None,
    max_results: int | None = None,
    max_pages: int = 5
) -> list[dict[str, str]]
ParameterTypeDescriptionPossible ValuesDefault
keywordsstrSearch query (required).Any string (e.g., "technology")Required
regionstrRegion code for localized results."wt-wt", "us-en", "uk-en", etc."wt-wt"
safesearchstrFilters explicit content."on", "moderate", "off""moderate"
timelimitstr | NoneLimits results by time."d" (day), "w" (week), "m" (month)None
max_resultsint | NoneMaximum number of results.Any positive integer (e.g., 3)None
max_pagesintMaximum pages to fetch.Any positive integer (e.g., 5)5
  • Returns: List of dictionaries with date (ISO format), title, body, url, image (optional), and source.

Common Features: All methods are asynchronous, validate keywords, use rate limiting, and support pagination via max_results and max_pages.

Usage Example
import asyncio
from asyncddgs import aDDGS

async def main():
    async with aDDGS() as ddgs:
        # Search for "technology" news with filters
        news_results = await ddgs.news(
            keywords="technology",
            region="us-en",
            safesearch="moderate",
            timelimit="d",
            max_results=2,
            max_pages=1
        )
        for result in news_results:
            print(f"Title: {result['title']}")
            print(f"Date: {result['date']}")
            print(f"URL: {result['url']}")
            print(f"Source: {result['source']}\n")

if __name__ == "__main__":
    asyncio.run(main())

Full Example

Here’s how to use the aDDGS class directly:

import asyncio
from asyncddgs import aDDGS

async def main():
    async with aDDGS(proxy="http://user:pass@proxy.example.com:3128") as ddgs:
        # Text search
        text_results = await ddgs.text("python programming", max_results=5)
        for result in text_results:
            print(f"Title: {result['title']}, URL: {result['href']}")

        # Image search
        image_results = await ddgs.images("sunset", size="Large", max_results=3)
        for result in image_results:
            print(f"Image: {result['image']}, Source: {result['source']}")

if __name__ == "__main__":
    asyncio.run(main())

This script demonstrates text and image searches with custom configuration (e.g., proxy). Adjust parameters as needed for other search types.

Running the API

Local Deployment

To launch the FastAPI application:

  • Ensure Dependencies are Installed: Complete the installation steps above.

  • Start the FastAPI Application:

    uvicorn app:app --host 0.0.0.0 --port 8080
    
    • app:app: Refers to the FastAPI instance in app.py.
    • --host 0.0.0.0: Allows external access.
    • --port 8080: Specifies the port.
  • Access the API:

    • Base URL: http://localhost:8080
    • Swagger UI: http://localhost:8080/docs

API Endpoints

The API exposes four endpoints for searching DuckDuckGo:

  • POST /text: Perform a text search.
  • POST /images: Perform an image search.
  • POST /videos: Perform a video search.
  • POST /news: Perform a news search.

Each endpoint accepts a JSON payload with specific parameters, detailed below with request bodies, response formats, parameter explanations, and examples.

Text Search (/text)

Endpoint: POST /text
Description: Queries DuckDuckGo for text-based search results, returning web page titles, URLs, and snippets. Supports advanced search syntax for precise queries.

Request Body:

{
  "keywords": "string",          // Required: Search query
  "region": "string",            // Optional: Region code (default: "wt-wt")
  "safesearch": "string",        // Optional: Safe search level (default: "moderate")
  "timelimit": "string",         // Optional: Time filter (e.g., "d", "w", "m", "y")
  "backend": "string",           // Optional: Backend (default: "auto")
  "max_results": integer,        // Optional: Maximum number of results
  "max_pages": integer           // Optional: Maximum pages to fetch (default: 5)
}

Response:

{
  "results": [
    {
      "title": "string",
      "href": "string",
      "body": "string"
    }
  ]
}

Parameters:

ParameterDescriptionPossible ValuesDefault
keywordsSearch query (required). Supports advanced syntax (see below).Any string (e.g., "python", "site:python.org")Required
regionRegion code for localized results."wt-wt" (worldwide), "us-en", "uk-en", "de-de", etc."wt-wt"
safesearchFilters explicit content."on", "moderate", "off""moderate"
timelimitLimits results by publication time."d" (day), "w" (week), "m" (month), "y" (year)None
backendSpecifies the DuckDuckGo backend to use."auto" (random), "html", "lite""auto"
max_resultsMaximum number of results to return.Any integer (e.g., 10)None
max_pagesMaximum number of result pages to fetch (each page triggers a request).Any integer (e.g., 5)5

Example Request:

curl -X POST "http://localhost:8080/text" -H "Content-Type: application/json" -d '{
  "keywords": "python programming site:python.org",
  "max_results": 5
}'

Example Response:

{
  "results": [
    {
      "title": "Python",
      "href": "https://www.python.org/",
      "body": "The official home of the Python Programming Language"
    },
    {
      "title": "Download Python",
      "href": "https://www.python.org/downloads/",
      "body": "Download the latest version of Python"
    }
  ]
}

Implementation Notes: The text endpoint uses either the "html" or "lite" backend, implemented in the standalone aDDGS class within app.py. If backend is "auto", it randomly selects between parsing full DuckDuckGo HTML pages (https://html.duckduckgo.com/html) or the lighter interface (https://lite.duckduckgo.com/lite/), returning deduplicated results.

Image Search (/images)

Endpoint: POST /images
Description: Retrieves image results from DuckDuckGo, including metadata like size, color, and license filters.

Request Body:

{
  "keywords": "string",          // Required: Search query
  "region": "string",            // Optional: Region code (default: "wt-wt")
  "safesearch": "string",        // Optional: Safe search level (default: "moderate")
  "timelimit": "string",         // Optional: Time filter (e.g., "Day", "Week")
  "size": "string",              // Optional: Image size filter
  "color": "string",             // Optional: Color filter
  "type_image": "string",        // Optional: Image type filter
  "layout": "string",            // Optional: Layout filter
  "license_image": "string",     // Optional: License filter
  "max_results": integer,        // Optional: Maximum number of results
  "max_pages": integer           // Optional: Maximum pages to fetch (default: 5)
}

Response:

{
  "results": [
    {
      "title": "string",
      "image": "string",
      "thumbnail": "string",
      "url": "string",
      "height": integer,
      "width": integer,
      "source": "string"
    }
  ]
}

Parameters:

ParameterDescriptionPossible ValuesDefault
keywordsSearch query (required).Any string (e.g., "sunset")Required
regionRegion code for localized results."wt-wt", "us-en", "uk-en", etc."wt-wt"
safesearchFilters explicit content."on", "moderate", "off""moderate"
timelimitLimits results by time."Day", "Week", "Month", "Year"None
sizeFilters by image size."Small", "Medium", "Large", "Wallpaper"None
colorFilters by image color."color", "Monochrome", "Red", "Orange", "Yellow", "Green", "Blue", "Purple", "Pink", "Brown", "Black", "Gray", "Teal", "White"None
type_imageFilters by image type."photo", "clipart", "gif", "transparent", "line"None
layoutFilters by image layout."Square", "Tall", "Wide"None
license_imageFilters by image license."any", "Public", "Share", "ShareCommercially", "Modify", "ModifyCommercially"None
max_resultsMaximum number of results.Any integer (e.g., 10)None
max_pagesMaximum pages to fetch.Any integer (e.g., 5)5

Example Request:

curl -X POST "http://localhost:8080/images" -H "Content-Type: application/json" -d '{
  "keywords": "sunset",
  "max_results": 10,
  "size": "Large",
  "color": "Orange"
}'

Example Response:

{
  "results": [
    {
      "title": "Sunset over the ocean",
      "image": "https://example.com/image.jpg",
      "thumbnail": "https://example.com/thumb.jpg",
      "url": "https://example.com",
      "height": 1080,
      "width": 1920,
      "source": "example.com"
    }
  ]
}

Implementation Notes: Uses the images method from the aDDGS class in app.py, querying https://duckduckgo.com/i.js with a vqd token. Results are deduplicated by image URL and paginated based on max_results or max_pages.

Video Search (/videos)

Endpoint: POST /videos
Description: Searches for videos on DuckDuckGo, returning video URLs and titles with filters for resolution and duration.

Request Body:

{
  "keywords": "string",          // Required: Search query
  "region": "string",            // Optional: Region code (default: "wt-wt")
  "safesearch": "string",        // Optional: Safe search level (default: "moderate")
  "timelimit": "string",         // Optional: Time filter (e.g., "d", "w", "m")
  "resolution": "string",        // Optional: Video resolution filter
  "duration": "string",          // Optional: Video duration filter
  "license_videos": "string",    // Optional: Video license filter
  "max_results": integer,        // Optional: Maximum number of results
  "max_pages": integer           // Optional: Maximum pages to fetch (default: 8)
}

Response:

{
  "results": [
    {
      "content": "string",
      "title": "string"
    }
  ]
}

Parameters:

ParameterDescriptionPossible ValuesDefault
keywordsSearch query (required).Any string (e.g., "python tutorials")Required
regionRegion code for localized results."wt-wt", "us-en", "uk-en", etc."wt-wt"
safesearchFilters explicit content."on", "moderate", "off""moderate"
timelimitLimits results by time."d" (day), "w" (week), "m" (month)None
resolutionFilters by video resolution."high", "standard"None
durationFilters by video duration."short", "medium", "long"None
license_videosFilters by video license."creativeCommon", "youtube"None
max_resultsMaximum number of results.Any integer (e.g., 5)None
max_pagesMaximum pages to fetch.Any integer (e.g., 8)8

Example Request:

curl -X POST "http://localhost:8080/videos" -H "Content-Type: application/json" -d '{
  "keywords": "python tutorials",
  "max_results": 5,
  "duration": "short"
}'

Example Response:

{
  "results": [
    {
      "content": "https://www.youtube.com/watch?v=abc123",
      "title": "Python Basics in 5 Minutes"
    }
  ]
}

Implementation Notes: Uses the videos method from aDDGS, querying https://duckduckgo.com/v.js. Results are deduplicated by video URL (content), with pagination up to max_pages (default 8).

News Search (/news)

Endpoint: POST /news
Description: Fetches news articles from DuckDuckGo, including publication dates, titles, and sources.

Request Body:

{
  "keywords": "string",          // Required: Search query
  "region": "string",            // Optional: Region code (default: "wt-wt")
  "safesearch": "string",        // Optional: Safe search level (default: "moderate")
  "timelimit": "string",         // Optional: Time filter (e.g., "d", "w", "m")
  "max_results": integer,        // Optional: Maximum number of results
  "max_pages": integer           // Optional: Maximum pages to fetch (default: 5)
}

Response:

{
  "results": [
    {
      "date": "string",  // ISO format
      "title": "string",
      "body": "string",
      "url": "string",
      "image": "string",
      "source": "string"
    }
  ]
}

Parameters:

ParameterDescriptionPossible ValuesDefault
keywordsSearch query (required).Any string (e.g., "technology")Required
regionRegion code for localized results."wt-wt", "us-en", "uk-en", etc."wt-wt"
safesearchFilters explicit content."on", "moderate", "off""moderate"
timelimitLimits results by time."d" (day), "w" (week), "m" (month)None
max_resultsMaximum number of results.Any integer (e.g., 3)None
max_pagesMaximum pages to fetch.Any integer (e.g., 5)5

Example Request:

curl -X POST "http://localhost:8080/news" -H "Content-Type: application/json" -d '{
  "keywords": "technology",
  "max_results": 3,
  "timelimit": "d"
}'

Example Response:

{
  "results": [
    {
      "date": "2025-03-30T12:00:00+00:00",
      "title": "New Tech Breakthrough",
      "body": "A summary of the article...",
      "url": "https://news.example.com/article",
      "image": "https://news.example.com/image.jpg",
      "source": "Tech News"
    }
  ]
}

Implementation Notes: Queries https://duckduckgo.com/news.js via the news method in aDDGS. Results include ISO-formatted dates and are deduplicated by URL.

Advanced Search Syntax

The keywords parameter in the /text endpoint supports DuckDuckGo's advanced search operators for precise queries. Below is a comprehensive table of operators as of March 31, 2025:

OperatorExampleResult
(space)cats dogsResults containing "cats" OR "dogs" (implicit OR)
"exact phrase""cats and dogs"Exact phrase match; falls back to related results if no exact match
-excludecats -dogsResults with "cats" but fewer or no "dogs"
+includecats +dogsResults with "cats" and more emphasis on "dogs"
filetype:cats filetype:pdfResults in specific file types (pdf, doc, docx, xls, xlsx, ppt, pptx, html)
site:dogs site:example.comResults from a specific site (e.g., example.com)
-site:cats -site:example.comExcludes results from a specific site
intitle:intitle:dogsResults with "dogs" in the page title
inurl:inurl:catsResults with "cats" in the URL
* (wildcard)cat*Matches variations (e.g., "cats", "caterpillar")
ORcats OR dogsResults containing either "cats" or "dogs" (case-sensitive operator)
() (grouping)(cats dogs) -miceGroups terms for complex queries; here, "cats" or "dogs" excluding "mice"
intext:intext:programmingResults with "programming" in the body text
allintitle:allintitle:cats dogsAll terms must appear in the title
allinurl:allinurl:cats dogsAll terms must appear in the URL
allintext:allintext:cats dogsAll terms must appear in the body text
related:related:python.orgResults related to a specific site
cache:cache:example.comCached version of a page (if available)
.. (range)phones 200..300Numeric range search (e.g., prices or years between 200 and 300)
# (hashtag)#pythonSocial media or tagged content related to "python"
@ (social handle)@pythondevResults mentioning a specific social media handle

Notes:

  • Combine operators (e.g., cats -dogs site:example.com filetype:pdf).
  • Some operators (e.g., cache:, related:) may have limited support due to DuckDuckGo's backend.
  • See DuckDuckGo's Help Pages on Syntax.

Implementation Impact: Operators are passed directly to DuckDuckGo via the keywords field and processed server-side, with backend options ensuring compatibility.

Using Proxies

Proxies route requests through alternative IPs for privacy or bypassing restrictions. Configure via the DDGS_PROXY environment variable.

Supported Formats:

  • HTTP: "http://user:pass@example.com:3128"
  • HTTPS: "https://user:pass@example.com:3128"
  • SOCKS5: "socks5://user:pass@example.com:1080"
  • Tor: "tb" (alias for "socks5://127.0.0.1:9150", requires Tor locally)

Example:

export DDGS_PROXY="http://user:pass@proxy.example.com:3128"
uvicorn src.app:app --host 0.0.0.0 --port 8080

Notes: The aDDGS class in app.py applies the proxy to all aiohttp requests, requiring valid credentials and connectivity.

Technical Details

Implementation Details

This API is a standalone implementation built with FastAPI and a custom aDDGS class (assumed in app.py).

  • Framework: FastAPI uses Python type hints for validation and generates Swagger UI at /docs.
  • Core Logic: The aDDGS class handles asynchronous requests to DuckDuckGo endpoints (html.duckduckgo.com/html, i.js, v.js, news.js) using aiohttp.
  • Rate Limiting: Configurable with a 20-second minimum interval and 0.75-second delay, ensuring compliance with DuckDuckGo's limits.
  • Error Handling: Custom exceptions (ValueValidationError, DuckDuckGoSearchException, TimeoutException) map to HTTP status codes (422, 500).
  • Response Processing: Results are normalized and deduplicated using sets for uniqueness.

Source: This is a custom module not yet published, with all logic contained in app.py.

Error Handling and Exceptions

Errors return structured responses with HTTP status codes:

  • 422 Unprocessable Entity: Invalid input (e.g., empty keywords), from ValueValidationError.
  • 500 Internal Server Error: Network issues, timeouts, or rate limits, from DuckDuckGoSearchException or TimeoutException.

Example Error Response:

{
  "detail": "keywords must not be empty or None"
}

Client Handling: Check status codes and detail for diagnostics; use backoff for 500 errors.

Docker Deployment

Docker ensures consistent deployment:

  • Install Docker:

  • Create a Dockerfile:

    FROM python:3.10-slim
    WORKDIR /app
    COPY app.py /app/app.py
    COPY requirements.txt /app/requirements.txt
    RUN pip install --no-cache-dir -r requirements.txt
    EXPOSE 8080
    CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "8080"]
    
  • Create requirements.txt:

    fastapi
    uvicorn
    pydantic
    aiohttp
    
  • Build the Image:

    docker build -t asyncddgs-app .
    
  • Run the Container:

    docker run -d -p 8080:8080 asyncddgs-app
    
  • Access the API:

    • URL: http://localhost:8080

With Proxy:

docker run -d -p 8080:8080 -e DDGS_PROXY="http://user:pass@proxy.example.com:3128" asyncddgs-app

Disclaimer

This API is not affiliated with DuckDuckGo and is intended for educational purposes only. It is not for commercial use or any purpose violating DuckDuckGo’s Terms of Service. Users must comply with DuckDuckGo’s terms at https://duckduckgo.com.

Updated as of April 01, 2025.

FAQs

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

About

Packages

Stay in touch

Get open source security insights delivered straight into your inbox.

  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc

U.S. Patent No. 12,346,443 & 12,314,394. Other pending.