I can not find a way to use duckduckgo to download images

When I tried using from duckduckgo_search import DDGS and I create this function:

def search_images(keywords, max_images = 1):
  results = DDGS().images(keywords, max_results = max_images)
  return L(r["image"] for r in results if "image" in r)

Then I tried to download 1 image to test if it’s working, but I’m getting this issue:

/usr/local/lib/python3.12/dist-packages/duckduckgo_search/duckduckgo_search.py in _get_url(self, method, url, params, content, data, headers, cookies, json, timeout)
    136         """Get vqd value for a search query."""
    137         resp_content = self._get_url("GET", "https://duckduckgo.com", params={"q": keywords})
--> 138         return _extract_vqd(resp_content, keywords)
    139 
    140     def chat(self, keywords: str, model: str = "gpt-4o-mini", timeout: int = 30) -> str:

RatelimitException: https://duckduckgo.com/i.js?o=json&q=black+bear&l=us-en&vqd=4-332971231917611368215991423545330450072&p=1&f=%2C%2C%2C%2C%2C 403 Ratelimit```

Does anyone know a solution for 2025? Thanks!
1 Like

You should use from ddgs import DDGS instead.
Tip: use pip install ddgs first.
If this problem persists, I think you need to check your ip (but I’m fairly confident that changing the import can solve your problem)

3 Likes

I have tried pip install ddgs but the error still comes. I think DuckDuckGo has changed it’s policy regarding downloading content since 2022.
I have found the kaggle datasets perfect for finding images, if you are using Kaggle.
If you are running locally or on any other platform like colab, i will suggest you to use bing_image_downloader . I tried this in a kaggle notebook for around 500 images, it was working fine. Here is the sample code -

!pip install bing_image_downloader

from bing_image_downloader import downloader
from pathlib import Path

CLASSES = ["Forest", "Bird"]
IMAGES_PER_CLASS = 50   # change as needed
BASE_DIR = Path("./images")

def download_images():
    for cls in CLASSES:
        downloader.download(
            query=cls,
            limit=IMAGES_PER_CLASS,
            output_dir=str(BASE_DIR),
            adult_filter_off=True,
            force_replace=False,
            timeout=60,
            verbose=True
        )

download_images()
3 Likes

Thanks! At the beginning of 2025, I used ddg to download all of the first generation of Pokémon so that I could create a classifier, and it worked perfectly. I’m not sure what happened since then because I was unable to use ddg.

1 Like

is it working?

I ran into the same issue and put a post on the Part 1 (2022) thread. Lesson 2 official topic - #906 by Studio

In short use this method. For some reason the color parameter is required.

def search_images(keywords, max_images=10, color='color'):
    results = DDGS().images(
        query=keywords,
        max_results=max_images,
        color=color,
    )
    return L(results).itemgot('image')
1 Like

Alternatively, you can try to use serp SerpApi: Python Integration or Bing Image Search Python client library.
I tested with serp, they offer a free tier

from serpapi import GoogleSearch
from fastcore.foundation import L
from dotenv import load_dotenv

load_dotenv() 
api_key = os.environ.get("SERP_API_KEY")

def search_images_serp(keywords, max_images=10):
        """Search for images using SerpApi and return original image URLs."""
        if not api_key:
            print("Error: SERPAPI_API_KEY not found. Make sure it's in your .env file.")
            return L()

        params = {
            "engine": "google_images",
            "q": keywords,
            "api_key": api_key,
        }

        search = GoogleSearch(params)
        results = search.get_dict()

        if "error" in results:
            print(f"SerpApi Error: {results['error']}")
            return L()

        image_results = results.get("images_results", [])
        return L(r['original'] for r in image_results[:max_images])
    return (search_images_serp,)

Thank you, this worked. I wonder why though

For anyone still having problem with this, first the duckduckgo library is now named ddgs so install it with pip install ddgs.

Then the client should be only instantiated once and then reused for our searches.

// change the import
from ddgs import DDGS

def search_images(keyword, client, max_images=50):
    raw = client.images(keyword, max_results=max_images)
    return L(raw).itemgot('image')

// example: instantiate the client first, then reuse it
client = DDGS()
for keyword in keywords:
  urls = search_images(keyword, client)