{
  "schemaVersion": "1.0",
  "item": {
    "slug": "ddg-search-privacy",
    "name": "Duckduckgo Search",
    "source": "tencent",
    "type": "skill",
    "category": "开发工具",
    "sourceUrl": "https://clawhub.ai/omprasad122007-rgb/ddg-search-privacy",
    "canonicalUrl": "https://clawhub.ai/omprasad122007-rgb/ddg-search-privacy",
    "targetPlatform": "OpenClaw"
  },
  "install": {
    "downloadMode": "redirect",
    "downloadUrl": "/downloads/ddg-search-privacy",
    "sourceDownloadUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=ddg-search-privacy",
    "sourcePlatform": "tencent",
    "targetPlatform": "OpenClaw",
    "installMethod": "Manual import",
    "extraction": "Extract archive",
    "prerequisites": [
      "OpenClaw"
    ],
    "packageFormat": "ZIP package",
    "includedAssets": [
      "scripts/duckduckgo_search.py",
      "SKILL.md"
    ],
    "primaryDoc": "SKILL.md",
    "quickSetup": [
      "Download the package from Yavira.",
      "Extract the archive and review SKILL.md first.",
      "Import or place the package into your OpenClaw setup."
    ],
    "agentAssist": {
      "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
      "steps": [
        "Download the package from Yavira.",
        "Extract it into a folder your agent can access.",
        "Paste one of the prompts below and point your agent at the extracted folder."
      ],
      "prompts": [
        {
          "label": "New install",
          "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Tell me what you changed and call out any manual steps you could not complete."
        },
        {
          "label": "Upgrade existing",
          "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Summarize what changed and any follow-up checks I should run."
        }
      ]
    },
    "sourceHealth": {
      "source": "tencent",
      "status": "healthy",
      "reason": "direct_download_ok",
      "recommendedAction": "download",
      "checkedAt": "2026-04-30T16:55:25.780Z",
      "expiresAt": "2026-05-07T16:55:25.780Z",
      "httpStatus": 200,
      "finalUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=network",
      "contentType": "application/zip",
      "probeMethod": "head",
      "details": {
        "probeUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=network",
        "contentDisposition": "attachment; filename=\"network-1.0.0.zip\"",
        "redirectLocation": null,
        "bodySnippet": null
      },
      "scope": "source",
      "summary": "Source download looks usable.",
      "detail": "Yavira can redirect you to the upstream package for this source.",
      "primaryActionLabel": "Download for OpenClaw",
      "primaryActionHref": "/downloads/ddg-search-privacy"
    },
    "validation": {
      "installChecklist": [
        "Use the Yavira download entry.",
        "Review SKILL.md after the package is downloaded.",
        "Confirm the extracted package contains the expected setup assets."
      ],
      "postInstallChecks": [
        "Confirm the extracted package includes the expected docs or setup files.",
        "Validate the skill or prompts are available in your target agent workspace.",
        "Capture any manual follow-up steps the agent could not complete."
      ]
    },
    "downloadPageUrl": "https://openagent3.xyz/downloads/ddg-search-privacy",
    "agentPageUrl": "https://openagent3.xyz/skills/ddg-search-privacy/agent",
    "manifestUrl": "https://openagent3.xyz/skills/ddg-search-privacy/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/ddg-search-privacy/agent.md"
  },
  "agentAssist": {
    "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
    "steps": [
      "Download the package from Yavira.",
      "Extract it into a folder your agent can access.",
      "Paste one of the prompts below and point your agent at the extracted folder."
    ],
    "prompts": [
      {
        "label": "New install",
        "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Tell me what you changed and call out any manual steps you could not complete."
      },
      {
        "label": "Upgrade existing",
        "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Summarize what changed and any follow-up checks I should run."
      }
    ]
  },
  "documentation": {
    "source": "clawhub",
    "primaryDoc": "SKILL.md",
    "sections": [
      {
        "title": "DuckDuckGo Web Search",
        "body": "Private web search using DuckDuckGo API for tracker-free information retrieval."
      },
      {
        "title": "Core Features",
        "body": "Privacy-focused search (no tracking)\nInstant answer support\nMultiple search modes (web, images, videos, news)\nJSON output for easy parsing\nNo API key required"
      },
      {
        "title": "Basic Web Search",
        "body": "import requests\n\ndef search_duckduckgo(query, max_results=10):\n    \"\"\"\n    Perform DuckDuckGo search and return results.\n\n    Args:\n        query: Search query string\n        max_results: Maximum number of results to return (default: 10)\n\n    Returns:\n        List of search results with title, url, description\n    \"\"\"\n    url = \"https://api.duckduckgo.com/\"\n    params = {\n        \"q\": query,\n        \"format\": \"json\",\n        \"no_html\": 1,\n        \"skip_disambig\": 0\n    }\n\n    response = requests.get(url, params=params)\n    data = response.json()\n\n    # Extract results\n    results = []\n\n    # Abstract (instant answer)\n    if data.get(\"Abstract\"):\n        results.append({\n            \"type\": \"instant_answer\",\n            \"title\": \"Instant Answer\",\n            \"content\": data[\"Abstract\"],\n            \"source\": data.get(\"AbstractSource\", \"DuckDuckGo\")\n        })\n\n    # Related topics\n    if data.get(\"RelatedTopics\"):\n        for topic in data[\"RelatedTopics\"][:max_results]:\n            if isinstance(topic, dict) and topic.get(\"Text\"):\n                results.append({\n                    \"type\": \"related\",\n                    \"title\": topic.get(\"FirstURL\", \"\").split(\"/\")[-1].replace(\"-\", \" \").title(),\n                    \"content\": topic[\"Text\"],\n                    \"url\": topic.get(\"FirstURL\", \"\")\n                })\n\n    return results[:max_results]"
      },
      {
        "title": "Advanced Usage (HTML Scraping)",
        "body": "from bs4 import BeautifulSoup\nimport requests\n\ndef search_with_results(query, max_results=10):\n    \"\"\"\n    Perform DuckDuckGo search and scrape actual results.\n\n    Args:\n        query: Search query string\n        max_results: Maximum number of results to return\n\n    Returns:\n        List of search results with title, url, snippet\n    \"\"\"\n    url = \"https://duckduckgo.com/html/\"\n    params = {\"q\": query}\n\n    headers = {\n        \"User-Agent\": \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36\"\n    }\n\n    response = requests.post(url, data=params, headers=headers)\n    soup = BeautifulSoup(response.text, \"html.parser\")\n\n    results = []\n    for result in soup.find_all(\"a\", class_=\"result__a\", href=True)[:max_results]:\n        results.append({\n            \"title\": result.get_text(),\n            \"url\": result[\"href\"],\n            \"snippet\": result.find_parent(\"div\", class_=\"result__body\").get_text().strip()\n        })\n\n    return results"
      },
      {
        "title": "Search Operators",
        "body": "DuckDuckGo supports standard search operators:\n\nOperatorExampleDescription\"\"\"exact phrase\"Exact phrase match-python -djangoExclude termssite:site:wikipedia.org historySearch specific sitefiletype:filetype:pdf reportSpecific file typesintitle:intitle:openclawWords in titleinurl:inurl:docs/Words in URLORdocker OR kubernetesEither term"
      },
      {
        "title": "Web Search",
        "body": "Default mode, searches across the web.\n\nsearch_with_results(\"machine learning tutorial\")"
      },
      {
        "title": "Images Search",
        "body": "def search_images(query, max_results=10):\n    url = \"https://duckduckgo.com/i.js\"\n    params = {\n        \"q\": query,\n        \"o\": \"json\",\n        \"vqd\": \"\",  # Will be populated\n        \"f\": \",,,\",\n        \"p\": \"1\"\n    }\n\n    response = requests.get(url, params=params)\n    data = response.json()\n\n    results = []\n    for result in data.get(\"results\", [])[:max_results]:\n        results.append({\n            \"title\": result.get(\"title\", \"\"),\n            \"url\": result.get(\"image\", \"\"),\n            \"thumbnail\": result.get(\"thumbnail\", \"\"),\n            \"source\": result.get(\"source\", \"\")\n        })\n\n    return results"
      },
      {
        "title": "News Search",
        "body": "Add !news to the query:\n\nsearch_duckduckgo(\"artificial intelligence !news\")"
      },
      {
        "title": "Query Construction",
        "body": "Good queries:\n\n\"DuckDuckGo API documentation\" 2024 (specific, recent)\nsite:github.com openclaw issues (targeted)\npython machine learning tutorial filetype:pdf (resource-specific)\n\nAvoid:\n\nVague single words (\"search\", \"find\")\nOverly complex operators that might confuse results\nQuestions with multiple unrelated topics"
      },
      {
        "title": "Privacy Considerations",
        "body": "DuckDuckGo advantages:\n\n✅ No personal tracking\n✅ No search history stored\n✅ No user profiling\n✅ No forced personalized results"
      },
      {
        "title": "Performance Tips",
        "body": "Use HTML scraping for actual results - The JSON API provides instant answers but limited result lists\nAdd appropriate delays - Respect rate limits when making multiple queries\nCache results - Store common searches to avoid repeated API calls"
      },
      {
        "title": "Error Handling",
        "body": "def search_safely(query, retries=3):\n    for attempt in range(retries):\n        try:\n            results = search_with_results(query)\n            if results:\n                return results\n        except Exception as e:\n            if attempt == retries - 1:\n                raise\n            time.sleep(2 ** attempt)  # Exponential backoff\n\n    return []"
      },
      {
        "title": "Markdown Format",
        "body": "def format_results_markdown(results, query):\n    output = f\"# Search Results for: {query}\\n\\n\"\n\n    for i, result in enumerate(results, 1):\n        output += f\"## {i}. {result.get('title', 'Untitled')}\\n\\n\"\n        output += f\"**URL:** {result.get('url', 'N/A')}\\n\\n\"\n        output += f\"{result.get('snippet', result.get('content', 'N/A'))}\\n\\n\"\n        output += \"---\\n\\n\"\n\n    return output"
      },
      {
        "title": "JSON Format",
        "body": "import json\n\ndef format_results_json(results, query):\n    return json.dumps({\n        \"query\": query,\n        \"count\": len(results),\n        \"results\": results,\n        \"timestamp\": datetime.now().isoformat()\n    }, indent=2)"
      },
      {
        "title": "Find Documentation",
        "body": "search_duckduckgo(f'{library_name} documentation filetype:md')"
      },
      {
        "title": "Recent Information",
        "body": "search_duckduckgo(f'{topic} 2024 news')"
      },
      {
        "title": "Troubleshooting",
        "body": "search_duckduckgo(f'{error_message} {tool_name} stackoverflow')"
      },
      {
        "title": "Technical Comparison",
        "body": "search_duckduckgo('postgresql vs mysql performance 2024')"
      },
      {
        "title": "Integration Example",
        "body": "class DuckDuckGoSearcher:\n    def __init__(self):\n        self.session = requests.Session()\n        self.session.headers.update({\n            \"User-Agent\": \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36\"\n        })\n\n    def search(self, query, mode=\"web\", max_results=10):\n        \"\"\"\n        Unified search interface.\n\n        Args:\n            query: Search query\n            mode: 'web', 'images', 'news'\n            max_results: Maximum results\n\n        Returns:\n            Formatted results as list\n        \"\"\"\n        if mode == \"images\":\n            return self._search_images(query, max_results)\n        elif mode == \"news\":\n            return self._search_web(f\"{query} !news\", max_results)\n        else:\n            return self._search_web(query, max_results)\n\n    def _search_web(self, query, max_results):\n        # Implementation\n        pass\n\n    def _search_images(self, query, max_results):\n        # Implementation\n        pass"
      },
      {
        "title": "Official Documentation",
        "body": "DuckDuckGo API Wiki: https://duckduckgo.com/api\nInstant Answer API: https://duckduckgo.com/params\nSearch Syntax: https://help.duckduckgo.com/duckduckgo-help-pages/results/syntax/"
      },
      {
        "title": "References",
        "body": "HTML scraping patterns for result extraction\nRate limiting best practices\nResult parsing and filtering"
      }
    ],
    "body": "DuckDuckGo Web Search\n\nPrivate web search using DuckDuckGo API for tracker-free information retrieval.\n\nCore Features\nPrivacy-focused search (no tracking)\nInstant answer support\nMultiple search modes (web, images, videos, news)\nJSON output for easy parsing\nNo API key required\nQuick Start\nBasic Web Search\nimport requests\n\ndef search_duckduckgo(query, max_results=10):\n    \"\"\"\n    Perform DuckDuckGo search and return results.\n\n    Args:\n        query: Search query string\n        max_results: Maximum number of results to return (default: 10)\n\n    Returns:\n        List of search results with title, url, description\n    \"\"\"\n    url = \"https://api.duckduckgo.com/\"\n    params = {\n        \"q\": query,\n        \"format\": \"json\",\n        \"no_html\": 1,\n        \"skip_disambig\": 0\n    }\n\n    response = requests.get(url, params=params)\n    data = response.json()\n\n    # Extract results\n    results = []\n\n    # Abstract (instant answer)\n    if data.get(\"Abstract\"):\n        results.append({\n            \"type\": \"instant_answer\",\n            \"title\": \"Instant Answer\",\n            \"content\": data[\"Abstract\"],\n            \"source\": data.get(\"AbstractSource\", \"DuckDuckGo\")\n        })\n\n    # Related topics\n    if data.get(\"RelatedTopics\"):\n        for topic in data[\"RelatedTopics\"][:max_results]:\n            if isinstance(topic, dict) and topic.get(\"Text\"):\n                results.append({\n                    \"type\": \"related\",\n                    \"title\": topic.get(\"FirstURL\", \"\").split(\"/\")[-1].replace(\"-\", \" \").title(),\n                    \"content\": topic[\"Text\"],\n                    \"url\": topic.get(\"FirstURL\", \"\")\n                })\n\n    return results[:max_results]\n\nAdvanced Usage (HTML Scraping)\nfrom bs4 import BeautifulSoup\nimport requests\n\ndef search_with_results(query, max_results=10):\n    \"\"\"\n    Perform DuckDuckGo search and scrape actual results.\n\n    Args:\n        query: Search query string\n        max_results: Maximum number of results to return\n\n    Returns:\n        List of search results with title, url, snippet\n    \"\"\"\n    url = \"https://duckduckgo.com/html/\"\n    params = {\"q\": query}\n\n    headers = {\n        \"User-Agent\": \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36\"\n    }\n\n    response = requests.post(url, data=params, headers=headers)\n    soup = BeautifulSoup(response.text, \"html.parser\")\n\n    results = []\n    for result in soup.find_all(\"a\", class_=\"result__a\", href=True)[:max_results]:\n        results.append({\n            \"title\": result.get_text(),\n            \"url\": result[\"href\"],\n            \"snippet\": result.find_parent(\"div\", class_=\"result__body\").get_text().strip()\n        })\n\n    return results\n\nSearch Operators\n\nDuckDuckGo supports standard search operators:\n\nOperator\tExample\tDescription\n\"\"\t\"exact phrase\"\tExact phrase match\n-\tpython -django\tExclude terms\nsite:\tsite:wikipedia.org history\tSearch specific site\nfiletype:\tfiletype:pdf report\tSpecific file types\nintitle:\tintitle:openclaw\tWords in title\ninurl:\tinurl:docs/\tWords in URL\nOR\tdocker OR kubernetes\tEither term\nSearch Modes\nWeb Search\n\nDefault mode, searches across the web.\n\nsearch_with_results(\"machine learning tutorial\")\n\nImages Search\ndef search_images(query, max_results=10):\n    url = \"https://duckduckgo.com/i.js\"\n    params = {\n        \"q\": query,\n        \"o\": \"json\",\n        \"vqd\": \"\",  # Will be populated\n        \"f\": \",,,\",\n        \"p\": \"1\"\n    }\n\n    response = requests.get(url, params=params)\n    data = response.json()\n\n    results = []\n    for result in data.get(\"results\", [])[:max_results]:\n        results.append({\n            \"title\": result.get(\"title\", \"\"),\n            \"url\": result.get(\"image\", \"\"),\n            \"thumbnail\": result.get(\"thumbnail\", \"\"),\n            \"source\": result.get(\"source\", \"\")\n        })\n\n    return results\n\nNews Search\n\nAdd !news to the query:\n\nsearch_duckduckgo(\"artificial intelligence !news\")\n\nBest Practices\nQuery Construction\n\nGood queries:\n\n\"DuckDuckGo API documentation\" 2024 (specific, recent)\nsite:github.com openclaw issues (targeted)\npython machine learning tutorial filetype:pdf (resource-specific)\n\nAvoid:\n\nVague single words (\"search\", \"find\")\nOverly complex operators that might confuse results\nQuestions with multiple unrelated topics\nPrivacy Considerations\n\nDuckDuckGo advantages:\n\n✅ No personal tracking\n✅ No search history stored\n✅ No user profiling\n✅ No forced personalized results\nPerformance Tips\nUse HTML scraping for actual results - The JSON API provides instant answers but limited result lists\nAdd appropriate delays - Respect rate limits when making multiple queries\nCache results - Store common searches to avoid repeated API calls\nError Handling\ndef search_safely(query, retries=3):\n    for attempt in range(retries):\n        try:\n            results = search_with_results(query)\n            if results:\n                return results\n        except Exception as e:\n            if attempt == retries - 1:\n                raise\n            time.sleep(2 ** attempt)  # Exponential backoff\n\n    return []\n\nOutput Formatting\nMarkdown Format\ndef format_results_markdown(results, query):\n    output = f\"# Search Results for: {query}\\n\\n\"\n\n    for i, result in enumerate(results, 1):\n        output += f\"## {i}. {result.get('title', 'Untitled')}\\n\\n\"\n        output += f\"**URL:** {result.get('url', 'N/A')}\\n\\n\"\n        output += f\"{result.get('snippet', result.get('content', 'N/A'))}\\n\\n\"\n        output += \"---\\n\\n\"\n\n    return output\n\nJSON Format\nimport json\n\ndef format_results_json(results, query):\n    return json.dumps({\n        \"query\": query,\n        \"count\": len(results),\n        \"results\": results,\n        \"timestamp\": datetime.now().isoformat()\n    }, indent=2)\n\nCommon Patterns\nFind Documentation\nsearch_duckduckgo(f'{library_name} documentation filetype:md')\n\nRecent Information\nsearch_duckduckgo(f'{topic} 2024 news')\n\nTroubleshooting\nsearch_duckduckgo(f'{error_message} {tool_name} stackoverflow')\n\nTechnical Comparison\nsearch_duckduckgo('postgresql vs mysql performance 2024')\n\nIntegration Example\nclass DuckDuckGoSearcher:\n    def __init__(self):\n        self.session = requests.Session()\n        self.session.headers.update({\n            \"User-Agent\": \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36\"\n        })\n\n    def search(self, query, mode=\"web\", max_results=10):\n        \"\"\"\n        Unified search interface.\n\n        Args:\n            query: Search query\n            mode: 'web', 'images', 'news'\n            max_results: Maximum results\n\n        Returns:\n            Formatted results as list\n        \"\"\"\n        if mode == \"images\":\n            return self._search_images(query, max_results)\n        elif mode == \"news\":\n            return self._search_web(f\"{query} !news\", max_results)\n        else:\n            return self._search_web(query, max_results)\n\n    def _search_web(self, query, max_results):\n        # Implementation\n        pass\n\n    def _search_images(self, query, max_results):\n        # Implementation\n        pass\n\nResources\nOfficial Documentation\nDuckDuckGo API Wiki: https://duckduckgo.com/api\nInstant Answer API: https://duckduckgo.com/params\nSearch Syntax: https://help.duckduckgo.com/duckduckgo-help-pages/results/syntax/\nReferences\nHTML scraping patterns for result extraction\nRate limiting best practices\nResult parsing and filtering"
  },
  "trust": {
    "sourceLabel": "tencent",
    "provenanceUrl": "https://clawhub.ai/omprasad122007-rgb/ddg-search-privacy",
    "publisherUrl": "https://clawhub.ai/omprasad122007-rgb/ddg-search-privacy",
    "owner": "omprasad122007-rgb",
    "version": "1.0.0",
    "license": null,
    "verificationStatus": "Indexed source record"
  },
  "links": {
    "detailUrl": "https://openagent3.xyz/skills/ddg-search-privacy",
    "downloadUrl": "https://openagent3.xyz/downloads/ddg-search-privacy",
    "agentUrl": "https://openagent3.xyz/skills/ddg-search-privacy/agent",
    "manifestUrl": "https://openagent3.xyz/skills/ddg-search-privacy/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/ddg-search-privacy/agent.md"
  }
}