{"id":2807,"date":"2026-10-19T08:32:39","date_gmt":"2026-10-19T15:32:39","guid":{"rendered":"https:\/\/www.five.reviews\/?p=2807"},"modified":"2026-10-19T08:32:40","modified_gmt":"2026-10-19T15:32:40","slug":"use-deepseek-search-api-and-fetch-api","status":"publish","type":"post","link":"https:\/\/www.five.reviews\/how-to\/use-deepseek-search-api-and-fetch-api\/","title":{"rendered":"How to Use DeepSeek Search API and Fetch API"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Language models cannot browse the web on their own, so AI applications need a way to find current sources and read them. <a href=\"https:\/\/api-docs.deepseek.com\/guides\/search\/\" target=\"_blank\" rel=\"noreferrer noopener\">The DeepSeek Search API<\/a> and Fetch API cover both steps. Search returns web pages that match a query, and Fetch retrieves the content of one page as Markdown. This tutorial shows how to authenticate, send requests, read responses, handle errors, and combine both endpoints in Python.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Quick Summary<\/strong><\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>The Search API (POST \/v1\/tools\/search) returns structured results for a query.<\/li>\n\n\n\n<li>The Fetch API (POST \/v1\/tools\/fetch) returns a page\u2019s title and content as Markdown.<\/li>\n\n\n\n<li>Both use bearer-token authentication and JSON request bodies.<\/li>\n\n\n\n<li>Python\u2019s requests library is enough. No SDK is required.<\/li>\n\n\n\n<li>Chaining the two lets an application search, choose a source, and read it, which supports research assistants, AI agents, and RAG pipelines.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>What Are the DeepSeek Search API and Fetch API?<\/strong><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">According to the official guide, both APIs give agents and RAG applications access to live web content. The Search API is powered by DeepSeek\u2019s in-house search engine.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>What Is the DeepSeek Search API?<\/strong><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The Search API takes a text query and returns a results array. Each item can include a title, URL, a short snippet for display, a longer summary for a model, and page content if you request it. A query with no matches returns an empty array, not an error.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>What Is the DeepSeek Fetch API?<\/strong><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The Fetch API takes one URL and returns the page\u2019s title and content, with the content in Markdown. Retrieval depends on the target site\u2019s availability and access policies, so some pages cannot be fetched.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>DeepSeek Search API vs. Fetch API<\/strong><\/h3>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td><\/td><td><strong>Search API<\/strong><\/td><td><strong>Fetch API<\/strong><\/td><\/tr><tr><td>Endpoint<\/td><td>\/v1\/tools\/search<\/td><td>\/v1\/tools\/fetch<\/td><\/tr><tr><td>Required input<\/td><td>query (1 to 128 characters)<\/td><td>url (HTTP or HTTPS, up to 8,192 characters)<\/td><\/tr><tr><td>Output<\/td><td>results array with metadata and snippets<\/td><td>title and Markdown content<\/td><\/tr><tr><td>Typical use<\/td><td>Discover candidate pages<\/td><td>Read a chosen page<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Search discovers pages. Fetch retrieves the one you pick.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>How to Set Up DeepSeek API Authentication<\/strong><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Create an API key on the<a href=\"https:\/\/platform.deepseek.com\/\" target=\"_blank\" rel=\"noreferrer noopener nofollow\"> DeepSeek Platform<\/a>, then store it in an environment variable rather than in your code:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">bash<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">export DEEPSEEK_API_KEY=&#8221;your-key-here&#8221; &nbsp; # macOS\/Linux<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">pip install requests<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Every request must send Authorization: Bearer &lt;DeepSeek API Key&gt; and Content-Type: application\/json. Never hardcode the key or print it in logs.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>How to Use the DeepSeek Search API<\/strong><\/h2>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Make Your First Search Request<\/strong><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">python<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">import os<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">import requests<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">headers = {<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;&#8220;Authorization&#8221;: f&#8221;Bearer {os.environ[&#8216;DEEPSEEK_API_KEY&#8217;]}&#8221;,<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;&#8220;Content-Type&#8221;: &#8220;application\/json&#8221;,<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">}<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">response = requests.post(<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;&#8220;https:\/\/api.deepseek.com\/v1\/tools\/search&#8221;,<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;headers=headers,<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;json={&#8220;query&#8221;: &#8220;DeepSeek V4 release&#8221;, &#8220;count&#8221;: 5, &#8220;need_content&#8221;: False},<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;timeout=30,<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">)<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">response.raise_for_status()<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">for result in response.json().get(&#8220;results&#8221;, []):<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;print(result.get(&#8220;title&#8221;), result.get(&#8220;url&#8221;))<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;print(result.get(&#8220;snippet&#8221;))<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Understand the Search Parameters<\/strong><\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>query<\/strong> (required): 1 to 128 Unicode characters, not all whitespace. Search operators are supported.<\/li>\n\n\n\n<li><strong>count<\/strong>: 1 to 50, default 10. It controls how many results return. It does not change the price.<\/li>\n\n\n\n<li><strong>need_content<\/strong>: default false. When false, content is an empty string. Enable it only when you need page text in the search response.<\/li>\n\n\n\n<li><strong>ori_question<\/strong>: optional, 1 to 128 characters. The user\u2019s original question, which helps the engine understand the query.<\/li>\n\n\n\n<li><strong>localization<\/strong>: optional IP address used to localize results.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Unknown fields are ignored.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Use Search Operators to Improve Results<\/strong><\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>DeepSeek site:github.com OR site:huggingface.co limits results to listed sites.<\/li>\n\n\n\n<li>DeepSeek -site:example.com excludes a site.<\/li>\n\n\n\n<li>&#8220;tool calling&#8221; DeepSeek matches an exact phrase.<\/li>\n\n\n\n<li>DeepSeek -advertisement or DeepSeek -&#8220;release notes&#8221; excludes a term or phrase.<\/li>\n\n\n\n<li>DeepSeek lang:zh,en filters by language codes.<\/li>\n\n\n\n<li>DeepSeek after:2025-01-01 before:2026-06-01 limits results to a publication window.<\/li>\n<\/ul>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>Understand the Search Response<\/strong><\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Each result can include these fields:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>rerank_score<\/strong> (0 to 3): a relevance score combining relevance, authority, and freshness. The guide treats 1.5 or higher as high quality.<\/li>\n\n\n\n<li><strong>authority<\/strong> (0 to 4, or -1 if unknown): an authority tier. Values of 3 or higher indicate highly authoritative sources.<\/li>\n\n\n\n<li><strong>snippet<\/strong>: a short display summary, typically 100 to 200 characters.<\/li>\n\n\n\n<li><strong>summary<\/strong>: a longer summary intended for a model, typically 600 to 800 characters.<\/li>\n\n\n\n<li><strong>date<\/strong>, <strong>site_name<\/strong>, <strong>site_icon<\/strong>: may be null.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">These are ranking signals. They do not confirm that a page is factually correct, so check important claims against more than one source.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>How to Use the DeepSeek Fetch API<\/strong><\/h2>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Fetch a Webpage With Python<\/strong><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">python<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">page = requests.post(<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;&#8220;https:\/\/api.deepseek.com\/v1\/tools\/fetch&#8221;,<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;headers=headers,<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;json={&#8220;url&#8221;: &#8220;https:\/\/example.com\/article&#8221;},<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;timeout=30,<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">)<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">page.raise_for_status()<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">data = page.json()<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">print(data.get(&#8220;title&#8221;, &#8220;&#8221;))<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">print(data.get(&#8220;content&#8221;, &#8220;&#8221;))<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Understand the Fetch API Response<\/strong><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The response contains title, which is empty when unavailable, and content, which is Markdown. The URL must be HTTP or HTTPS, include a host, contain no username or password, and be no longer than 8,192 characters.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">A 404 means Fetch could not retrieve usable content. Causes include an unavailable URL, a site policy block, an upstream error, an unsupported content type, or a page with no extractable Markdown. A 403 means the request was rejected by security policy.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Process Retrieved Markdown<\/strong><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">You can save the content to a file, display it, or pass it to a language model. Check that content is not empty before using it, and treat it as untrusted input, because a web page can contain text that looks like instructions.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Combine DeepSeek Search and Fetch APIs in Python<\/strong><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">This workflow searches for a topic, ranks the results, skips unusable candidates, fetches the best one, and prints its Markdown. It reads the key from os.environ, uses explicit timeouts, retries only the statuses the guide marks as retryable, and validates each URL before fetching.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">python<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">import os<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">import sys<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">import time<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">from urllib.parse import urlparse<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">import requests<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">BASE_URL = &#8220;https:\/\/api.deepseek.com&#8221;<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">SEARCH_URL = f&#8221;{BASE_URL}\/v1\/tools\/search&#8221;<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">FETCH_URL = f&#8221;{BASE_URL}\/v1\/tools\/fetch&#8221;<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">TIMEOUT_SECONDS = 30<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">MAX_ATTEMPTS = 3<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">MAX_FETCH_CANDIDATES = 3<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">def get_headers():<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;api_key = os.environ.get(&#8220;DEEPSEEK_API_KEY&#8221;)<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;if not api_key:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;raise RuntimeError(&#8220;DEEPSEEK_API_KEY is not set.&#8221;)<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;return {<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8220;Authorization&#8221;: f&#8221;Bearer {api_key}&#8221;,<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8220;Content-Type&#8221;: &#8220;application\/json&#8221;,<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;}<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">def is_safe_url(url):<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;&#8220;&#8221;&#8221;Basic validation only. It is not a complete defense against SSRF.&#8221;&#8221;&#8221;<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;if not isinstance(url, str) or not url or len(url) &gt; 8192:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return False<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;try:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;parsed = urlparse(url)<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;except ValueError:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return False<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;return (<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;parsed.scheme in (&#8220;http&#8221;, &#8220;https&#8221;)<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;and bool(parsed.hostname)<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;and not parsed.username<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;and not parsed.password<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;)<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">def post_json(url, payload):<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;&#8220;&#8221;&#8221;POST with a timeout. Retries only 408, 429, and 5xx responses.&#8221;&#8221;&#8221;<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;for attempt in range(1, MAX_ATTEMPTS + 1):<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;response = requests.post(<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;url, headers=get_headers(), json=payload, timeout=TIMEOUT_SECONDS<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;)<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if response.ok:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return response.json()<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;retryable = response.status_code in (408, 429) or response.status_code &gt;= 500<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if not retryable or attempt == MAX_ATTEMPTS:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;response.raise_for_status()<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;time.sleep(2 ** attempt)<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">def search(query, count=5):<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;data = post_json(SEARCH_URL, {&#8220;query&#8221;: query, &#8220;count&#8221;: count, &#8220;need_content&#8221;: False})<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;return data.get(&#8220;results&#8221;) or []<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">def fetch(url):<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;return post_json(FETCH_URL, {&#8220;url&#8221;: url})<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">def main():<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;query = &#8221; &#8220;.join(sys.argv[1:]).strip() or &#8220;DeepSeek API documentation&#8221;<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;if len(query) &gt; 128:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print(&#8220;Query must be 128 characters or fewer.&#8221;)<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return 1<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;try:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;results = search(query)<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;except requests.RequestException as err:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print(f&#8221;Search failed: {err}&#8221;)<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return 1<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;candidates = [r for r in results if is_safe_url(r.get(&#8220;url&#8221;))]<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;candidates.sort(key=lambda r: r.get(&#8220;rerank_score&#8221;) or 0, reverse=True)<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;if not candidates:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print(&#8220;No usable search results.&#8221;)<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return 0<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;for item in candidates[:MAX_FETCH_CANDIDATES]:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;try:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;page = fetch(item[&#8220;url&#8221;])<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;except requests.RequestException as err:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print(f&#8221;Skipping {item[&#8216;url&#8217;]}: {err}&#8221;)<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;continue<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;content = (page.get(&#8220;content&#8221;) or &#8220;&#8221;).strip()<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if not content:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print(f&#8221;Skipping {item[&#8216;url&#8217;]}: no content returned.&#8221;)<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;continue<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print(f&#8221;Title: {page.get(&#8216;title&#8217;) or item.get(&#8216;title&#8217;) or &#8216;Untitled&#8217;}&#8221;)<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print(f&#8221;URL: {item[&#8216;url&#8217;]}\\n&#8221;)<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print(content[:2000])<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return 0<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;print(&#8220;None of the top candidates could be fetched.&#8221;)<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;return 1<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">if __name__ == &#8220;__main__&#8221;:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;raise SystemExit(main())<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Run it with python research.py &#8220;DeepSeek V4 release&#8221;. The script covers each step as follows:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>It reads the key from DEEPSEEK_API_KEY.<\/li>\n\n\n\n<li>It sends a search request with a bounded count.<\/li>\n\n\n\n<li>It returns early when results is empty.<\/li>\n\n\n\n<li>It sorts candidates by rerank_score, treating missing scores as zero.<\/li>\n\n\n\n<li>It validates each URL\u2019s scheme, host, credentials, and length.<\/li>\n\n\n\n<li>It calls the Fetch endpoint for up to three candidates.<\/li>\n\n\n\n<li>It catches HTTP errors and timeouts, retrying only 408, 429, and 5xx responses.<\/li>\n\n\n\n<li>It prints the title, URL, and the first 2,000 characters of Markdown. Remove the slice to print the full content.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">To extend this into a research assistant or RAG pipeline, pass the fetched Markdown and its URL into your model prompt, store the URL with each chunk, and keep the source attached to every answer. Search and Fetch retrieve content, but they do not guarantee that an answer is verified.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>DeepSeek Search and Fetch API Pricing, Rate Limits, and Errors<\/strong><\/h2>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td><strong>Endpoint<\/strong><\/td><td><strong>Billing unit<\/strong><\/td><td><strong>Price<\/strong><\/td><\/tr><tr><td>Search<\/td><td>Per 1,000 successful requests<\/td><td>$0.75<\/td><\/tr><tr><td>Fetch<\/td><td>Per 1,000 successful requests<\/td><td>$0.75<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">A request is billable only when it returns HTTP 200 with a non-empty results array (Search) or page content (Fetch). Failed requests, empty results, and timeouts are not billed.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The guide also says that server-side tool calls made through DeepSeek Harness, Claude Code, or Codex are currently free. Per-request billing for those calls begins at 00:00 Beijing time on November 1, 2026. This does not change the pricing above for direct API calls.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Each account has independent limits of 5 requests per second for Search and 5 for Fetch. Fetch also has a per-domain limit, which the guide does not specify. Exceeding a limit returns HTTP 429.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td><strong>Status<\/strong><\/td><td><strong>Meaning<\/strong><\/td><td><strong>Action<\/strong><\/td><\/tr><tr><td>400<\/td><td>Invalid headers, body, or field value<\/td><td>Fix the request. Do not retry unchanged.<\/td><\/tr><tr><td>401<\/td><td>Missing or invalid API key<\/td><td>Check the key.<\/td><\/tr><tr><td>402<\/td><td>Insufficient balance<\/td><td>Top up, then retry.<\/td><\/tr><tr><td>403<\/td><td>Fetch rejected by security policy<\/td><td>Use a different URL.<\/td><\/tr><tr><td>404<\/td><td>Fetch could not retrieve usable content<\/td><td>Try another source.<\/td><\/tr><tr><td>408<\/td><td>Request body read timed out<\/td><td>Wait and retry.<\/td><\/tr><tr><td>413<\/td><td>Request body too large<\/td><td>Reduce the payload.<\/td><\/tr><tr><td>429<\/td><td>Search or Fetch QPS limit exceeded<\/td><td>Wait and retry with backoff.<\/td><\/tr><tr><td>500<\/td><td>Internal server error<\/td><td>Wait and retry.<\/td><\/tr><tr><td>504<\/td><td>Downstream request timed out<\/td><td>Wait and retry.<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Best Practices for DeepSeek API Integration<\/strong><\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Keep the API key in an environment variable or secret manager, and keep it out of logs and error messages.<\/li>\n\n\n\n<li>Narrow queries with operators such as site:, lang:, and date filters before raising count. Operators improve relevance, while count only adds results.<\/li>\n\n\n\n<li>Fetch a few high-ranked, high-authority sources rather than every result, since each fetch is billed and limited to 5 per second.<\/li>\n\n\n\n<li>Set need_content to true only when you need page text in the search response.<\/li>\n\n\n\n<li>Throttle your own loops to stay below 5 requests per second per endpoint.<\/li>\n\n\n\n<li>Treat fetched Markdown as untrusted input, and keep it separate from your instructions when you pass it to a model.<\/li>\n\n\n\n<li>Keep each source URL with the text it supports so that users can verify it.<\/li>\n\n\n\n<li>Recheck the official guide for pricing and limits before deployment, because the guide notes that these may change.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Conclusion<\/strong><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Search finds the pages, and Fetch reads the ones you choose. Start by running the individual endpoints with a narrow query, then add the combined script to your application. Before production use, check the official guide for current pricing, limits, and the status of the free arrangement for Harness, Claude Code, and Codex.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Frequently Asked Questions<\/strong><\/h2>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>What is the DeepSeek Search API used for?<\/strong><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">It finds web pages for a text query and returns structured results with titles, URLs, snippets, and summaries. Developers use it in <a href=\"https:\/\/www.five.reviews\/ai-tools\/ai-agents-vs-ai-assistants\/\" target=\"_blank\" rel=\"noreferrer noopener\">AI agents<\/a> and RAG applications to discover current sources. Query operators can restrict results by domain, language, and publication date.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>What is the difference between DeepSeek Search API and Fetch API?<\/strong><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The Search API discovers candidate pages and returns metadata for each. The Fetch API takes one URL and returns that page\u2019s title and content as Markdown. A common workflow runs Search first, selects a result, and then sends its URL to Fetch.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>How do you use the DeepSeek Search API in Python?<\/strong><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Send a POST request to https:\/\/api.deepseek.com\/v1\/tools\/search with a bearer token in the Authorization header and a JSON body containing a query. You can add count and need_content. Call raise_for_status(), then read the results array from the response.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>How do you use the DeepSeek Fetch API in Python?<\/strong><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Send a POST request to https:\/\/api.deepseek.com\/v1\/tools\/fetch with the same authentication and a JSON body containing url. The URL must be HTTP or HTTPS, include a host, and contain no credentials. Read title and content from the response.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Do DeepSeek Search and Fetch APIs require the OpenAI SDK?<\/strong><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">No. The guide describes both as raw JSON APIs that use the same bearer authentication as the DeepSeek API. You can call them with Python\u2019s requests library, curl, or any HTTP client.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>How much do DeepSeek Search and Fetch APIs cost?<\/strong><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Each costs $0.75 per 1,000 successful requests, according to the official guide. Only HTTP 200 responses that return results or page content are billed. Certain server-side calls through DeepSeek Harness, <a href=\"https:\/\/www.five.reviews\/ai-tools\/claude-code-vs-codex\/\" target=\"_blank\" rel=\"noreferrer noopener\">Claude Code<\/a>, or Codex are currently free, with billing starting November 1, 2026.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>What does the DeepSeek Fetch API return?<\/strong><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">It returns a JSON object with title and content. The title is empty when unavailable. The content is the page text in Markdown. Content may be empty, so check it before use. Retrieval depends on the target site\u2019s availability and access policies.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Can DeepSeek Fetch retrieve any webpage?<\/strong><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">No. Fetch returns 404 when it cannot produce usable content, such as for unavailable URLs, blocked pages, unsupported content types, or pages with no extractable Markdown. It returns 403 when a request violates its security policy.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>What should you do when the DeepSeek API returns a 429 error?<\/strong><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">A 429 means the Search or Fetch QPS limit was exceeded. Wait, then retry with exponential backoff. Limits are 5 requests per second per endpoint for each account, and Fetch also has a per-domain limit. Throttle your own requests to stay under them.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Can DeepSeek Search and Fetch APIs be used in RAG applications?<\/strong><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Yes. The official guide says both serve agents and RAG applications. Search finds sources, and Fetch retrieves their content for chunking and embedding. Retrieved text is not automatically verified, so store source URLs and check important claims.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Language models cannot browse the web on their own, so AI applications need a way to find current sources and read them. The DeepSeek [&hellip;]<\/p>\n","protected":false},"author":5,"featured_media":2808,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[6],"tags":[304,1220,1218,1222,1223,1221,1219,1224],"content_cluster":[7],"content_type":[21],"search_intent":[24],"tool_category":[28],"class_list":["post-2807","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-how-to","tag-ai-development","tag-api-authentication","tag-deepseek-api","tag-deepseek-api-tutorial","tag-deepseek-fetch-api","tag-deepseek-search-api","tag-python-api-integration","tag-web-search-api","content_cluster-how-to","content_type-how-to-guide","search_intent-informational","tool_category-ai-writing"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.five.reviews\/?rest_route=\/wp\/v2\/posts\/2807","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.five.reviews\/?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.five.reviews\/?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.five.reviews\/?rest_route=\/wp\/v2\/users\/5"}],"replies":[{"embeddable":true,"href":"https:\/\/www.five.reviews\/?rest_route=%2Fwp%2Fv2%2Fcomments&post=2807"}],"version-history":[{"count":1,"href":"https:\/\/www.five.reviews\/?rest_route=\/wp\/v2\/posts\/2807\/revisions"}],"predecessor-version":[{"id":2809,"href":"https:\/\/www.five.reviews\/?rest_route=\/wp\/v2\/posts\/2807\/revisions\/2809"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.five.reviews\/?rest_route=\/wp\/v2\/media\/2808"}],"wp:attachment":[{"href":"https:\/\/www.five.reviews\/?rest_route=%2Fwp%2Fv2%2Fmedia&parent=2807"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.five.reviews\/?rest_route=%2Fwp%2Fv2%2Fcategories&post=2807"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.five.reviews\/?rest_route=%2Fwp%2Fv2%2Ftags&post=2807"},{"taxonomy":"content_cluster","embeddable":true,"href":"https:\/\/www.five.reviews\/?rest_route=%2Fwp%2Fv2%2Fcontent_cluster&post=2807"},{"taxonomy":"content_type","embeddable":true,"href":"https:\/\/www.five.reviews\/?rest_route=%2Fwp%2Fv2%2Fcontent_type&post=2807"},{"taxonomy":"search_intent","embeddable":true,"href":"https:\/\/www.five.reviews\/?rest_route=%2Fwp%2Fv2%2Fsearch_intent&post=2807"},{"taxonomy":"tool_category","embeddable":true,"href":"https:\/\/www.five.reviews\/?rest_route=%2Fwp%2Fv2%2Ftool_category&post=2807"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}