Discover/Duck API
live

Duck APIduck.ai

Retrieve Duck.ai AI model configurations, capabilities, access tiers, supported tools, and live service status via two simple REST endpoints.

This API takes change requests — .
Endpoint health
verified 3d ago
get_models
get_status
2/2 passing latest checkself-healing
Endpoints
2
Updated
1d ago

What is the Duck API?

The Duck.ai API exposes 2 endpoints that return structured data about DuckDuckGo's private AI chat service. The get_models endpoint delivers a full list of available AI models — including provider, capabilities, supported tools, file type support, and subscription tier requirements — plus a ready-to-use JavaScript export string. The get_status endpoint reports current service health so you can confirm availability before making downstream calls.

This call costs1 credit / call— charged only on success
Try it

No input parameters required.

api.parse.bot/scraper/ec7d8282-525d-433a-9943-342788add371/<endpoint>
Ready to send
Fill in the parameters and hit sign in to send to see live response data here.
Call it over HTTPgrab a free API key at signup
curl -X GET 'https://api.parse.bot/scraper/ec7d8282-525d-433a-9943-342788add371/get_models' \
  -H 'X-API-Key: $PARSE_API_KEY'
Python SDK · recommended

Typed, relational, agent-ready

A generated client with real types, enums, and the links between objects — the structure a flat JSON response can't carry. Autocompletes in your editor and reads cleanly to coding agents.

  • Fully typed · autocompletes
  • Objects link to objects
  • Typed errors & pagination

Typed Python client. Set up the SDK in your uv project, then pull this API’s typed client:

uv add parse-sdk
uv run parse init
uv run parse add --marketplace duck-ai-api

uv run parse add --marketplace pulls a pinned snapshot of this canonical API — it won’t change underneath you. To customize it, subscribe and swap to your own copy.

"""
Duck.ai Models API Client
Retrieve AI model data and service status from Duck.ai (DuckDuckGo's private AI chat).
Get your API key from: https://parse.bot/settings
"""

import os
import json
import requests
from typing import Any, Dict, List, Optional


class ParseClient:
    """Client for interacting with Duck.ai Models API via Parse.bot"""

    def __init__(self, api_key: Optional[str] = None):
        """
        Initialize the Parse API client.
        
        Args:
            api_key: API key for authentication. If not provided, reads from PARSE_API_KEY env var.
        """
        self.base_url = "https://api.parse.bot"
        self.scraper_id = "ec7d8282-525d-433a-9943-342788add371"
        self.api_key = api_key or os.getenv("PARSE_API_KEY")
        
        if not self.api_key:
            raise ValueError("API key is required. Set PARSE_API_KEY environment variable or pass api_key parameter.")

    def _call(self, endpoint: str, method: str = "POST", **params) -> Dict[str, Any]:
        """
        Make an API call to the Parse endpoint.
        
        Args:
            endpoint: The endpoint name (e.g., 'get_models', 'get_status')
            method: HTTP method ('GET' or 'POST')
            **params: Additional parameters to pass to the endpoint
            
        Returns:
            Response data as a dictionary
            
        Raises:
            requests.RequestException: If the API call fails
        """
        url = f"{self.base_url}/scraper/{self.scraper_id}/{endpoint}"
        headers = {
            "X-API-Key": self.api_key,
            "Content-Type": "application/json"
        }
        
        if method.upper() == "GET":
            response = requests.get(url, headers=headers, params=params)
        else:
            payload = params if params else {}
            response = requests.post(url, headers=headers, json=payload)
        
        response.raise_for_status()
        return response.json()

    def get_models(self) -> Dict[str, Any]:
        """
        Fetch all available AI models from Duck.ai.
        
        Returns information about model capabilities, providers, access tiers,
        supported tools, and file type support.
        
        Returns:
            Dictionary containing:
            - models: List of model objects with configurations
            - attachment_limits: File/image upload limits per subscription tier
            - javascript: Pre-formatted JavaScript export string
            - total_models: Count of models returned
        """
        return self._call("get_models", method="GET")

    def get_status(self) -> Dict[str, Any]:
        """
        Fetch the current Duck.ai service status.
        
        Returns:
            Dictionary containing:
            - status: Primary status code (0 = operational)
            - secondaryStatus: Secondary status code
            - statusV2: V2 status code
        """
        return self._call("get_status", method="GET")


def analyze_model_ecosystem(models: List[Dict[str, Any]]) -> Dict[str, Any]:
    """
    Analyze the Duck.ai model ecosystem to extract insights.
    
    Args:
        models: List of model objects from get_models response
        
    Returns:
        Dictionary with ecosystem analysis
    """
    analysis = {
        "total_models": len(models),
        "providers": {},
        "access_tiers": {},
        "tools_coverage": {},
        "image_support": 0,
        "pdf_support": 0,
        "reasoning_support": 0,
    }
    
    for model in models:
        # Provider stats
        provider = model.get("provider", "unknown").upper()
        if provider not in analysis["providers"]:
            analysis["providers"][provider] = {
                "count": 0,
                "models": [],
                "max_access_tier": "free"
            }
        analysis["providers"][provider]["count"] += 1
        analysis["providers"][provider]["models"].append(model.get("name"))
        
        # Access tier stats
        tiers = model.get("accessTier", [])
        for tier in tiers:
            if tier not in analysis["access_tiers"]:
                analysis["access_tiers"][tier] = 0
            analysis["access_tiers"][tier] += 1
        
        # Tools coverage
        tools = model.get("supportedTools", [])
        for tool in tools:
            if tool not in analysis["tools_coverage"]:
                analysis["tools_coverage"][tool] = []
            analysis["tools_coverage"][tool].append(model.get("name"))
        
        # Feature support
        if model.get("supportsImageUpload"):
            analysis["image_support"] += 1
        
        file_types = model.get("supportedFileTypes", [])
        if "application/pdf" in file_types:
            analysis["pdf_support"] += 1
        
        reasoning = model.get("supportedReasoningEffort", [])
        if len(reasoning) > 1:  # More than just "none"
            analysis["reasoning_support"] += 1
    
    return analysis


def filter_models_by_tier(models: List[Dict[str, Any]], tier: str) -> List[Dict[str, Any]]:
    """
    Filter models available for a specific access tier.
    
    Args:
        models: List of model objects
        tier: Access tier ('free', 'plus', 'pro', 'internal')
        
    Returns:
        List of models available in the specified tier
    """
    return [m for m in models if tier in m.get("accessTier", [])]


def find_best_model_for_task(models: List[Dict[str, Any]], 
                             requires_images: bool = False,
                             requires_pdf: bool = False,
                             requires_web_search: bool = False,
                             tier: str = "pro") -> Optional[Dict[str, Any]]:
    """
    Find the best model that matches specific requirements.
    
    Args:
        models: List of model objects
        requires_images: Whether image upload capability is needed
        requires_pdf: Whether PDF file support is needed
        requires_web_search: Whether web search tool is needed
        tier: Minimum access tier required
        
    Returns:
        Best matching model or None if no match found
    """
    candidates = filter_models_by_tier(models, tier)
    
    for model in candidates:
        if requires_images and not model.get("supportsImageUpload"):
            continue
        
        if requires_pdf and "application/pdf" not in model.get("supportedFileTypes", []):
            continue
        
        if requires_web_search and "WebSearch" not in model.get("supportedTools", []):
            continue
        
        return model
    
    return None


def main():
    """Practical workflow: Check service health, analyze models, and find optimal models for tasks."""
    
    # Initialize the client
    client = ParseClient()
    
    print("\n" + "=" * 80)
    print("DUCK.AI MODELS ANALYSIS WORKFLOW")
    print("=" * 80)
    
    # Step 1: Check service status
    print("\n[1/5] Checking Duck.ai service status...")
    try:
        status_response = client.get_status()
        status_code = int(status_response.get("status", -1))
        
        if status_code == 0:
            print("✓ Duck.ai service is OPERATIONAL")
        else:
            print(f"✗ Service degraded - Status code: {status_code}")
            print(f"  Secondary status: {status_response.get('secondaryStatus', 'unknown')}")
            return
    except Exception as e:
        print(f"✗ Failed to check service status: {e}")
        return
    
    # Step 2: Fetch all available models
    print("\n[2/5] Fetching available AI models...")
    try:
        models_response = client.get_models()
        models = models_response.get("models", [])
        total_models = models_response.get("total_models", 0)
        attachment_limits = models_response.get("attachment_limits", {})
        
        print(f"✓ Retrieved {total_models} models from Duck.ai")
    except Exception as e:
        print(f"✗ Failed to fetch models: {e}")
        return
    
    # Step 3: Analyze ecosystem
    print("\n[3/5] Analyzing model ecosystem...")
    analysis = analyze_model_ecosystem(models)
    
    print("\n  Provider Distribution:")
    for provider, data in sorted(analysis["providers"].items()):
        model_names = ", ".join(data["models"][:2])
        suffix = f" (+{len(data['models'])-2} more)" if len(data["models"]) > 2 else ""
        print(f"    • {provider:15} {data['count']:2} models  ({model_names}{suffix})")
    
    print("\n  Feature Support:")
    print(f"    • Models with image upload:    {analysis['image_support']}/{total_models}")
    print(f"    • Models with PDF support:     {analysis['pdf_support']}/{total_models}")
    print(f"    • Models with reasoning effort: {analysis['reasoning_support']}/{total_models}")
    
    print("\n  Available Tools:")
    for tool, model_names in sorted(analysis["tools_coverage"].items()):
        print(f"    • {tool:25} {len(model_names)} models")
    
    print("\n  Access Tier Distribution:")
    for tier, count in sorted(analysis["access_tiers"].items(), 
                               key=lambda x: {"free": 0, "plus": 1, "pro": 2, "internal": 3}.get(x[0], 99)):
        print(f"    • {tier:10} {count:2} models")
    
    # Step 4: Find models for specific use cases
    print("\n[4/5] Finding optimal models for specific use cases...")
    
    use_cases = [
        {
            "name": "Document Analysis (PDF + Images)",
            "requires_pdf": True,
            "requires_images": True,
            "tier": "pro"
        },
        {
            "name": "Web Research with AI",
            "requires_web_search": True,
            "tier": "plus"
        },
        {
            "name": "Free Tier Analysis",
            "tier": "free"
        }
    ]
    
    for use_case in use_cases:
        best_model = find_best_model_for_task(
            models,
            requires_images=use_case.get("requires_images", False),
            requires_pdf=use_case.get("requires_pdf", False),
            requires_web_search=use_case.get("requires_web_search", False),
            tier=use_case["tier"]
        )
        
        status = "✓" if best_model else "✗"
        if best_model:
            print(f"  {status} {use_case['name']:40} → {best_model.get('name')}")
        else:
            print(f"  {status} {use_case['name']:40} → No matching model")
    
    # Step 5: Display subscription tier information
    print("\n[5/5] Subscription tier limits...")
    
    tier_order = ["free", "plus", "pro"]
    for tier in tier_order:
        if tier in attachment_limits:
            limits = attachment_limits[tier]
            files = limits.get("files", {})
            images = limits.get("images", {})
            
            tier_display = tier.upper()
            print(f"\n  {tier_display} Tier:")
            print(f"    Files:   {files.get('maxPerConversation', '?')} per conversation, " 
                  f"max {files.get('maxFileSizeMB', '?')}MB, " 
                  f"{files.get('maxPagesPerFile', '?')} pages per file")
            print(f"    Images:  {images.get('maxPerTurn', '?')} per turn, " 
                  f"{images.get('maxPerConversation', '?')} per conversation")
    
    # Summary
    print("\n" + "=" * 80)
    print("WORKFLOW COMPLETE")
    print(f"Total models analyzed: {total_models}")
    print(f"Providers: {len(analysis['providers'])}")
    print(f"Tools available: {len(analysis['tools_coverage'])}")
    print("=" * 80 + "\n")


if __name__ == "__main__":
    main()
All endpoints · 2 totalmissing one? ·

Fetches all available AI models from Duck.ai including their capabilities, providers, access tiers, supported tools, and file type support. Returns structured model data along with a pre-formatted JavaScript export string. No parameters required — returns the full model catalog in a single response.

Input

No input parameters required.

Response
{
  "type": "object",
  "fields": {
    "models": "array of model objects with id, provider, name, capabilities, and access tier info",
    "javascript": "string containing the model data formatted as JavaScript export statements",
    "total_models": "integer count of models returned",
    "attachment_limits": "object with file and image upload limits per subscription tier (free, plus, pro)"
  },
  "sample": {
    "data": {
      "models": [
        {
          "id": "gpt-5.4",
          "name": "GPT-5.4",
          "provider": "openai",
          "modelName": "GPT-5.4",
          "settingId": "261",
          "accessTier": [
            "internal",
            "plus",
            "pro"
          ],
          "modelVariant": null,
          "modelShortName": "GPT-5.4",
          "supportedTools": [
            "WebSearch",
            "SearchResults",
            "RelatedSearchTerms"
          ],
          "entityHasAccess": false,
          "supportedFileTypes": [
            "application/pdf"
          ],
          "supportsImageUpload": true,
          "reasoningEffortAccess": [
            {
              "id": "none",
              "accessTier": [
                "internal",
                "plus",
                "pro"
              ],
              "entityHasAccess": false
            }
          ],
          "supportedReasoningEffort": [
            "none",
            "low",
            "medium"
          ]
        }
      ],
      "javascript": "const duckAIModels = [...];\n\nconst attachmentLimits = {...};\n\nexport { duckAIModels, attachmentLimits };\n",
      "total_models": 8,
      "attachment_limits": {
        "pro": {
          "files": {
            "maxFileSizeMB": 25,
            "maxPagesPerFile": 50,
            "maxPerConversation": 5,
            "maxTotalFileSizeBytes": 26214400
          },
          "images": {
            "maxPerTurn": 3,
            "maxPerConversation": 10,
            "maxInputCharsWithAttachments": 4500
          }
        },
        "free": {
          "files": {
            "maxFileSizeMB": 5,
            "maxPagesPerFile": 15,
            "maxPerConversation": 3,
            "maxTotalFileSizeBytes": 5242880
          },
          "images": {
            "maxPerTurn": 3,
            "maxPerConversation": 5,
            "maxInputCharsWithAttachments": 4500
          }
        },
        "plus": {
          "files": {
            "maxFileSizeMB": 25,
            "maxPagesPerFile": 35,
            "maxPerConversation": 5,
            "maxTotalFileSizeBytes": 26214400
          },
          "images": {
            "maxPerTurn": 3,
            "maxPerConversation": 10,
            "maxInputCharsWithAttachments": 4500
          }
        }
      }
    },
    "status": "success"
  }
}

About the Duck API

Model Data

The get_models endpoint returns an array of model objects, each containing fields such as id, provider, name, capabilities, and access tier information indicating whether a model is available on free, plus, or pro plans. The response also includes attachment_limits, an object that maps each subscription tier (free, plus, pro) to its file and image upload constraints. A total_models integer gives you a quick count without iterating the array. Alongside the structured data, the endpoint returns a javascript string — a pre-formatted export statement you can drop directly into a JS/TS project.

Service Status

The get_status endpoint returns three fields: status (a string code where "0" indicates fully operational), statusV2 (an integer version of the same signal), and secondaryStatus (a secondary string code for more granular health information). This is useful for uptime checks, conditional logic before triggering AI requests, or surfacing degraded-state warnings in a UI.

What the API Covers

Both endpoints require no input parameters — all responses are returned in full. The model data reflects the live Duck.ai catalog, including which models are gated behind paid tiers and what file types each model can accept as attachments. There is no filtering or pagination; you receive the complete dataset on every call.

Reliability & maintenanceVerified

The Duck API is a managed, monitored endpoint for duck.ai — not a raw scraper you maintain. Every endpoint is automatically health-checked on a schedule, and when duck.ai changes and a check fails, the API is automatically queued for repair and re-verified. It is built to keep working as the site underneath it changes.

This isn't an official duck.ai API — it's an independent, maintained REST wrapper over public data. Where the source has no official API (or only a limited one), Parse gives you a stable contract over a source that never promised one, and keeps it current. Need a new endpoint or field? You can revise it yourself in plain English and the agent rebuilds it against the live site in minutes — contributing the change back to the shared API is free.

Last verified
3d ago
Latest check
2/2 endpoints passing
Maintenance
Monitored & self-healing
Will this API break when the source site changes?+
It's built not to. Every endpoint is health-checked on a schedule with automated test probes. When the source site changes and a check fails, the API is automatically queued for repair and re-verified — that's the self-healing layer. Each API page shows when its endpoints were last verified. And because marketplace APIs are shared, any fix reaches everyone using it.
Is this an official API from the source site?+
No — Parse APIs are independent, managed REST wrappers over publicly available data. That is the point: where a site has no official API (or only a limited one), Parse gives you a maintained, monitored endpoint for that data and keeps it working as the site changes — so you get a stable contract over a source that never promised one.
Can I fix or extend this API myself if I need a new endpoint or field?+
Yes — and you don't have to wait on us. This API was generated by the Parse agent, which stays attached. Describe the change in plain English ("add an endpoint that returns reviews", "fix the price field") in the revise box on the API page or via the revise_api MCP tool, and the agent rebuilds it against the live site in minutes. Contributing the change back to the public API is free.
What happens if I call an endpoint that has an issue?+
Errors are machine-readable: a bad call returns a clean status with the list of available endpoints and a repair hint, so an agent (or you) can recover or trigger a fix instead of failing silently. Confirmed failures feed the automatic repair queue.
Common use cases
  • Build a model-picker UI that filters Duck.ai models by access tier (free, plus, or pro) using the capabilities and tier fields.
  • Display attachment constraints to users before they upload files, using the attachment_limits object keyed by subscription tier.
  • Run an uptime monitor that polls get_status and alerts when the status field is non-zero.
  • Auto-generate TypeScript type definitions for Duck.ai models using the javascript export string returned by get_models.
  • Track changes in the Duck.ai model catalog over time by recording total_models and model id lists on a schedule.
  • Gate AI chat features in your app behind a live availability check using statusV2 from get_status.
Pricing & limitsSee full pricing →
TierPriceCredits/monthRate limit
Free$0/mo1005 req/min
Hobby$30/mo1,00020 req/min
Developer$100/mo5,000100 req/min

One credit = one API call regardless of which marketplace API you call. Exceeding the rate limit returns a 429 response. Authenticate with the X-API-Key header.

Frequently asked questions
Does Duck.ai have an official public developer API?+
DuckDuckGo does not publish an official developer API for Duck.ai. This Parse API provides structured access to model and status data from the service.
What does the `get_models` endpoint return beyond a list of model names?+
Each model object includes id, provider, name, capabilities, and access tier details showing which subscription plans can use it. The response also includes attachment_limits (per-tier file and image upload constraints) and a javascript field containing the full model dataset as a pre-formatted JS export string.
Does the API expose individual chat completions or message history from Duck.ai?+
No. The API covers model configurations and service status only — it does not send messages, retrieve conversation history, or return AI-generated responses. You can fork this API on Parse and revise it to add an endpoint targeting that functionality.
How granular is the service status data?+
The get_status endpoint returns three fields: a status string ("0" = operational), a statusV2 integer, and a secondaryStatus string. It does not break down status by individual model or geographic region. You can fork the API on Parse and revise it to add more granular health endpoints if needed.
Can I filter `get_models` results to a specific provider or tier?+
The endpoint returns the full model list with no server-side filtering — all filtering must be done client-side using the provider and access tier fields in each model object. You can fork this API on Parse and revise it to add query parameters that pre-filter by provider or tier.
Page content last updated . Spec covers 2 endpoints from duck.ai.
Related APIs in Developer ToolsSee all →
crt.sh API
Search for SSL/TLS certificates across public transparency logs by domain, fingerprint, serial number, or public key, and retrieve detailed certificate information including issuer, validity dates, and certificate chain details. Monitor certificate issuance for domains you care about to track security changes and detect unauthorized certificates.
artificialanalysis.ai API
Compare and rank LLM models and providers across performance benchmarks, then dive into detailed specifications for any model to find the best fit for your needs. Discover performance metrics for specialized AI systems handling speech, images, and video, plus benchmark data for different hardware configurations.
python.org API
Access comprehensive Python release information including downloads, versions, and supported operating systems, plus stay updated with the latest Python news and events. Search across Python.org's resources and browse release files, details, and the FTP index all in one place.
nvidia.com API
nvidia.com API
alienvault.com API
Search and analyze global threat intelligence data including indicators of compromise, threat pulses, and adversary profiles from the Open Threat Exchange community. Monitor recent security alerts and access detailed information about threats and adversaries to strengthen your cybersecurity defenses.
lucide.dev API
Browse and download thousands of Lucide icons with instant search and category filtering to find exactly what you need. Get SVG files and metadata for each icon to integrate them seamlessly into your projects.
trends.google.com API
Discover what's trending right now in any country by accessing the top search topics with real-time search volume, growth rates, and related queries. Stay informed on trending categories and see which searches are gaining the most momentum in your target markets.
soliditylang.org API
Access comprehensive Solidity documentation, search language references, and browse blog posts to stay updated on development news. Query compiler bug data filtered by version to identify known issues and compatibility concerns across smart contract projects.