<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Sergey Ermakovich</title>
    <description>The latest articles on DEV Community by Sergey Ermakovich (@ermakovich_sergey).</description>
    <link>https://dev.to/ermakovich_sergey</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3075350%2Fc71fe283-e344-4107-b1c9-9e11969abb6b.png</url>
      <title>DEV Community: Sergey Ermakovich</title>
      <link>https://dev.to/ermakovich_sergey</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ermakovich_sergey"/>
    <language>en</language>
    <item>
      <title>DuckDuckGo MCP Servers in Claude Code: 8 Tested, 3 Actually Work</title>
      <dc:creator>Sergey Ermakovich</dc:creator>
      <pubDate>Wed, 23 Sep 2026 07:09:55 +0000</pubDate>
      <link>https://dev.to/hasdata_com/duckduckgo-mcp-servers-in-claude-code-8-tested-3-actually-work-3gnp</link>
      <guid>https://dev.to/hasdata_com/duckduckgo-mcp-servers-in-claude-code-8-tested-3-actually-work-3gnp</guid>
      <description>&lt;p&gt;Free web search for an agent sounds like a solved problem. There are dozens of DuckDuckGo MCP servers, none of them wants an API key, and every catalog lists them with the same three-line description lifted from the README.&lt;/p&gt;

&lt;p&gt;So I installed eight of them and gave each one the same job: twelve research questions, one after another, no pause between them. That is roughly what a coding agent does when it starts digging into an unfamiliar library. Three servers answered all twelve. One of them was not talking to DuckDuckGo at all.&lt;/p&gt;

&lt;p&gt;I work at HasData and we run one of the eight. It came third on speed in the first pass and fourth in the two after, behind free servers. Every config below is copy-paste ready, and the harness is public if you want to rerun any of it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The setup
&lt;/h2&gt;

&lt;p&gt;Twelve queries, from &lt;code&gt;rust async runtime comparison&lt;/code&gt; to &lt;code&gt;solar inverter efficiency&lt;/code&gt;, sent back to back through the official MCP TypeScript SDK. Then the whole thing twice more, about an hour apart, to see what was stable. One machine, one IP, 2026-09-15.&lt;/p&gt;

&lt;p&gt;A call counted as a failure if the server errored, if the body was an error dressed as a result, or if it came back with nothing in it. That third rule did most of the work.&lt;/p&gt;

&lt;p&gt;Here is the whole test on one screen, ordered by how often each server finished and then by speed.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Server&lt;/th&gt;
&lt;th&gt;Install&lt;/th&gt;
&lt;th&gt;Finished, 3 passes&lt;/th&gt;
&lt;th&gt;Median&lt;/th&gt;
&lt;th&gt;Payload&lt;/th&gt;
&lt;th&gt;Returns&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;free-search-mcp&lt;/td&gt;
&lt;td&gt;&lt;code&gt;uvx free-search-mcp&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;12, 12, 12&lt;/td&gt;
&lt;td&gt;1.39 s&lt;/td&gt;
&lt;td&gt;4.2 KB&lt;/td&gt;
&lt;td&gt;markdown, JSON on request&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HasData (ours)&lt;/td&gt;
&lt;td&gt;hosted, no install&lt;/td&gt;
&lt;td&gt;12, 12, 12&lt;/td&gt;
&lt;td&gt;1.96 s&lt;/td&gt;
&lt;td&gt;10.0 KB&lt;/td&gt;
&lt;td&gt;JSON&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;nickclyde&lt;/td&gt;
&lt;td&gt;&lt;code&gt;uvx duckduckgo-mcp-server&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;12, 12, 12&lt;/td&gt;
&lt;td&gt;2.37 s&lt;/td&gt;
&lt;td&gt;3.6 KB&lt;/td&gt;
&lt;td&gt;text&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;open-webSearch&lt;/td&gt;
&lt;td&gt;&lt;code&gt;npx open-websearch&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;10, 12, 12&lt;/td&gt;
&lt;td&gt;1.12 s&lt;/td&gt;
&lt;td&gt;5.4 KB&lt;/td&gt;
&lt;td&gt;JSON&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;one-search-mcp&lt;/td&gt;
&lt;td&gt;&lt;code&gt;npx one-search-mcp&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;12, 12, 12&lt;/td&gt;
&lt;td&gt;7.27 s&lt;/td&gt;
&lt;td&gt;4.9 KB&lt;/td&gt;
&lt;td&gt;text, Bing results&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;OEvortex&lt;/td&gt;
&lt;td&gt;&lt;code&gt;npx @oevortex/ddg_search&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;3, 6, 2&lt;/td&gt;
&lt;td&gt;1.53 s&lt;/td&gt;
&lt;td&gt;1.2 KB&lt;/td&gt;
&lt;td&gt;text&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;web-scout&lt;/td&gt;
&lt;td&gt;&lt;code&gt;npx @pinkpixel/web-scout-mcp&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;1, 0, 1&lt;/td&gt;
&lt;td&gt;1.51 s&lt;/td&gt;
&lt;td&gt;4.0 KB&lt;/td&gt;
&lt;td&gt;text&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;zhsama&lt;/td&gt;
&lt;td&gt;&lt;code&gt;npx duckduckgo-mcp-server&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;0, 0, 0&lt;/td&gt;
&lt;td&gt;n/a&lt;/td&gt;
&lt;td&gt;n/a&lt;/td&gt;
&lt;td&gt;n/a&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The medians only count calls that returned something, so the bottom three look faster than they are. OEvortex failing in 1.53 s is still a failure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Start here if you just want one that works
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mcpServers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"duckduckgo"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"uvx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"free-search-mcp"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;free-search-mcp&lt;/code&gt; answered twelve of twelve in every pass at a 1.39 s median, the fastest of the servers that finished. It is a 69-star project, MIT, last pushed in August 2026, so it is young. It returns markdown by default. If your agent would rather have JSON, ask for it per call:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"query"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"rust async runtime comparison"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"engines"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"duckduckgo"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"format"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"json"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"use_cache"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Three arguments is more config than the others need, and &lt;code&gt;use_cache&lt;/code&gt; defaults to true, which will quietly hand you an old answer if you leave it alone. That is the trade for the best numbers in the test.&lt;/p&gt;

&lt;h2&gt;
  
  
  The one everybody installs
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mcpServers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"duckduckgo"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"uvx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"duckduckgo-mcp-server"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;nickclyde's server is the default choice for good reason: 1,460 stars, pushed this month, MIT, and it is what the &lt;code&gt;mcp/duckduckgo&lt;/code&gt; Docker image is built from, with over half a million pulls. It finished twelve of twelve in all three passes at 2.37 s, then came apart on a fourth run from a fresh clone, answering seven and refusing five with a note about DuckDuckGo's bot detection and a suggestion to install its optional browser backend for Chrome TLS impersonation.&lt;/p&gt;

&lt;p&gt;It answers in prose, &lt;code&gt;Found N search results:&lt;/code&gt; followed by a numbered list, so your model does the parsing. Its search tool takes a query, a result count and a region, and there is no pagination.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Watch the command.&lt;/strong&gt; This is &lt;code&gt;duckduckgo-mcp-server&lt;/code&gt; on PyPI, hence &lt;code&gt;uvx&lt;/code&gt;. There is an unrelated &lt;code&gt;duckduckgo-mcp-server&lt;/code&gt; on npm, and this config gets you a completely different server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mcpServers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"duckduckgo"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"-y"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"duckduckgo-mcp-server"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That one is zhsama's, and it scored zero of twelve in all three passes. Google's AI Overview for the package name currently recommends the npm version.&lt;/p&gt;

&lt;h2&gt;
  
  
  The hosted one, which is ours
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mcpServers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"duckduckgo"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://mcp.hasdata.com/api/mcp?apis=duckduckgo"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"headers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"x-api-key"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"YOUR-KEY"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Twelve of twelve in all three passes at a 1.96 s median, which put it third on speed in the first pass and fourth in the two after, behind free servers. That is the honest placement and it is the least interesting number here.&lt;/p&gt;

&lt;p&gt;What it does differently is the payload. Ten results carrying position, title, link, displayedLink, source, snippet and snippetHighlightedWords, plus DuckDuckGo's own assist answer with its sources and a pagination token. Nothing else in the test paginates, and only open-webSearch and free-search return JSON at all. The cost of that is weight: 10.0 KB per call against nickclyde's 3.6, which your agent pays for in context.&lt;/p&gt;

&lt;p&gt;The other difference is the one I did not expect to matter. Time from cold config to first answer was 2.3 s, against 8.3 s for free-search, 8.8 s for nickclyde and 37 to 48 s for open-webSearch and OEvortex, which spend it resolving and building packages. There is nothing on your machine to install or keep current, and nothing that breaks when a transitive dependency moves.&lt;/p&gt;

&lt;p&gt;It is the only server in the test that costs money past a free tier of 100 searches a month, with paid plans running from $2.95 down to $0.83 per thousand. Details and the free key are on the &lt;a href="https://hasdata.com/mcp/duckduckgo" rel="noopener noreferrer"&gt;server page&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What went wrong, server by server
&lt;/h2&gt;

&lt;h3&gt;
  
  
  zhsama, zero of twelve, three times
&lt;/h3&gt;

&lt;p&gt;Ten of its twelve calls came back in two to five milliseconds with a 26-byte error. Nothing reaches the network that fast. Its own stderr names the culprit:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;[DEBUG] Rate limit check - Current counts: { second: 1, month: 2, lastReset: ... }
[ERROR] Rate limit exceeded
    at checkRateLimit (.../duckduckgo-mcp-server/build/index.js:80:23)
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The shipped build sets &lt;code&gt;rateLimit: { perSecond: 1, perMonth: 15000 }&lt;/code&gt;. So &lt;code&gt;{ second: 1, month: 2 }&lt;/code&gt; is a counter, not a budget, and what stopped the run is one request per second. The server throws instead of queueing, which is the part that matters for an agent: a burst of twelve gets ten hard errors rather than twelve slow answers.&lt;/p&gt;

&lt;p&gt;Pace your calls a second apart and you clear its limiter. The two that did get through reached DuckDuckGo and were turned away there anyway.&lt;/p&gt;

&lt;h3&gt;
  
  
  web-scout, one of twelve
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"mcpServers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"duckduckgo"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"-y"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@pinkpixel/web-scout-mcp"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It answered the first query in 1.5 s and then returned this eleven times, each in under 310 ms:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;No results were found for your search query. Please try rephrasing your search or try again in a few minutes.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No error flag, no status code, just a sentence. Your agent sees a successful tool call with a polite message and concludes the web has nothing on Postgres index bloat.&lt;/p&gt;

&lt;h3&gt;
  
  
  OEvortex, three then six then two
&lt;/h3&gt;

&lt;p&gt;Nine of twelve failed with &lt;code&gt;HTTP 202: Failed to fetch search results&lt;/code&gt;, and the successes landed on calls eight, nine and twelve. Rerun an hour later it scored six, then two. That spread is not a rate limit being hit. A limit cuts in and stays cut in. This is a wrapper that works sometimes.&lt;/p&gt;

&lt;h3&gt;
  
  
  open-webSearch, the fastest thing here and the quietest failure
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mcpServers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"duckduckgo"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"-y"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"open-websearch"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"env"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"MODE"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"stdio"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"DEFAULT_SEARCH_ENGINE"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"duckduckgo"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;1.12 s median, JSON with direct links, five fields per result including which engine produced it. It lost two of twelve in the first pass and none in the two after.&lt;/p&gt;

&lt;p&gt;Those two look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"query"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"bird migration patterns europe"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"engines"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"duckduckgo"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"totalResults"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"results"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"partialFailures"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note the last field. The server has somewhere to report that an engine failed and left it empty while returning nothing. Its stderr for those exact two calls says it could not find the preloaded &lt;code&gt;d.js&lt;/code&gt; URL it scrapes out of DuckDuckGo's HTML, so the diagnosis exists, it just never reaches the caller.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;MODE: stdio&lt;/code&gt; in that config is not optional if you run it more than once. By default it also binds an HTTP server on port 3000, and a leftover instance from an earlier session makes the next one die with &lt;code&gt;MCP error -32000: Connection closed&lt;/code&gt;, which tells you nothing about ports.&lt;/p&gt;

&lt;h3&gt;
  
  
  one-search-mcp, which was searching Bing
&lt;/h3&gt;

&lt;p&gt;This is the one worth ten minutes of your attention. Its tool schema has no engine parameter, so I ran it as shipped, and it looked fine: twelve of twelve, 7.27 s each, well-formed results. Then I looked at the URLs. Every one was a &lt;code&gt;bing.com/ck/a&lt;/code&gt; redirect. Not a single duckduckgo.com address in any response.&lt;/p&gt;

&lt;p&gt;The server reads &lt;code&gt;SEARCH_PROVIDER&lt;/code&gt; from the environment. The default is &lt;code&gt;local&lt;/code&gt;, which launches your real Chrome profile and scrapes Bing. Set it properly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mcpServers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"search"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"-y"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"one-search-mcp"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"env"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"SEARCH_PROVIDER"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"duckduckgo"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and it returns zero of twelve, each call failing after ten to sixteen seconds with DuckDuckGo's anomaly message and &lt;code&gt;Failed to get the VQD&lt;/code&gt; in its log. So its DuckDuckGo path does not work from here, and its working path is not DuckDuckGo.&lt;/p&gt;

&lt;p&gt;The Bing redirect is not automatically a problem, since DuckDuckGo's organic index is largely Bing-sourced anyway. The problem is a URL that hides its destination in a base64 parameter, which quietly breaks deduplication and domain filters in whatever you build on top.&lt;/p&gt;

&lt;h2&gt;
  
  
  The rule that would have caught half of this
&lt;/h2&gt;

&lt;p&gt;Three of the eight fail inside a successful tool call. Two return an empty array, one returns a prose sentence. If your agent checks for errors and then reads results, all three look like a search that found nothing.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;failed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isError&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
  &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isArray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
  &lt;span class="sr"&gt;/no results|bot detection|rate limit|anomaly/i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two details from the run. The array check alone misses web-scout, which returns no array at all. And an immediate retry does not help, because open-webSearch returned empty twice in a row, so back off with a cap and fail over to a second server instead.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I kept
&lt;/h2&gt;

&lt;p&gt;For hand-driven searching, &lt;code&gt;free-search-mcp&lt;/code&gt; with the engine pinned and the cache off. It never missed a call in three passes and it is the fastest of the ones that finished.&lt;/p&gt;

&lt;p&gt;For an agent that runs unattended, the requirement is JSON with real links plus the check above, and that is a format question rather than a reliability one. nickclyde and free-search were just as reliable as anything else and both answer in prose. open-webSearch gives you JSON out of the box and is the one that silently empties. &lt;a href="https://hasdata.com/mcp/duckduckgo" rel="noopener noreferrer"&gt;Ours&lt;/a&gt; gives you JSON with pagination, did not miss a call in forty-eight, starts answering in a couple of seconds with nothing installed, returns the heaviest payload here at 10 KB against nickclyde's 3.6, and costs money past a hundred searches a month.&lt;/p&gt;

&lt;p&gt;On these numbers I would start with the free one and add the check.&lt;/p&gt;

&lt;p&gt;The harness, the fixture and the twelve queries are at &lt;a href="https://github.com/HasData/mcp-bench" rel="noopener noreferrer"&gt;github.com/HasData/mcp-bench&lt;/a&gt;. Results move by IP and by day, so if yours disagree with mine I would rather know.&lt;/p&gt;

</description>
      <category>mpc</category>
      <category>ai</category>
      <category>webdev</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Zillow MCP Server Comparison: 6 Tested, 3 Actually Work</title>
      <dc:creator>Sergey Ermakovich</dc:creator>
      <pubDate>Tue, 15 Sep 2026 07:57:55 +0000</pubDate>
      <link>https://dev.to/hasdata_com/zillow-mcp-server-comparison-6-tested-3-actually-work-16kn</link>
      <guid>https://dev.to/hasdata_com/zillow-mcp-server-comparison-6-tested-3-actually-work-16kn</guid>
      <description>&lt;p&gt;The task was small. An agent in Claude Code that, given "two-bedroom rentals in Denver under $2,500", lists what is on Zillow right now and pulls the full record for anything we like. Zillow has no API for that and no MCP server of its own, so the work is choosing a third-party MCP server. We wired up six of them on 2026-09-09, ran the same rental search through each three times, and kept notes. The setup for each, what came back, and what broke.&lt;/p&gt;

&lt;h2&gt;
  
  
  The test
&lt;/h2&gt;

&lt;p&gt;One search, rentals in Denver, CO, three calls per server, from the official MCP TypeScript SDK as a client with a 240 second timeout. We counted a call as failed when the tool returned an error, when it returned an error dressed as a normal result, or when it returned an empty list. Latency is the median of the successful calls.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;| Server                  | Setup            | Denver rentals, 3 calls                      | p50    |
|-------------------------|------------------|----------------------------------------------|--------|
| HasData Zillow MCP      | hosted, API key  | 3/3, 41 rentals x 21 fields, 159 KB JSON     | 5.4 s  |
| Apify, afanasenko actor | hosted, token    | 3/3, 15 rentals x 77 fields, 42 KB JSON      | 7.2 s  |
| Apify, maxcopell actor  | hosted, token    | 3/3 in two calls, 40 rentals x 17 fields, 168 KB | 13.0 s |
| APIllow                 | local, uvx, key  | 3/3 answered, 5 results with sale prices     | 16.5 s |
| @striderlabs/mcp-zillow | local, from src  | 3/3 answered, total_found: 0                 | 4.2 s  |
| chrischall/zillow-mcp   | local, npx       | 0/6, needs your logged-in browser            | n/a    |
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  1. HasData
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://hasdata.com/mcp/zillow" rel="noopener noreferrer"&gt;HasData's Zillow server&lt;/a&gt; is hosted, streamable HTTP, two tools. Add it to Claude Code with the key in a header:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;claude mcp add &lt;span class="nt"&gt;--transport&lt;/span&gt; http zillow &lt;span class="s2"&gt;"https://mcp.hasdata.com/api/mcp?apis=zillow"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s2"&gt;"x-api-key: &lt;/span&gt;&lt;span class="nv"&gt;$HASDATA_API_KEY&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The search tool takes a place name and a type, so the benchmark call was &lt;code&gt;{"keyword": "Denver, CO", "type": "forRent"}&lt;/code&gt; with no translation step, the same broad query every server got. It came back in 3.5 to 8.7 seconds with 41 rentals and 21 fields each, price, beds, baths, area, address, days on Zillow, home type, the listing URL, and a total-results count. The tool also has the filters the agent needs, so the real task is one call with &lt;code&gt;beds_min_&lt;/code&gt; and &lt;code&gt;price_max_&lt;/code&gt; set, and Zillow does the narrowing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;request&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"keyword"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Denver, CO"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"forRent"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"beds_min_"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"price_max_"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2500&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;response,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;first&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;listing&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;of&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;41&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;647&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;total)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"465129302"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"price"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1595&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"beds"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"baths"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"area"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;805&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"addressRaw"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"975-979 S Lowell Blvd #977, Denver, CO 80219"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"daysOnZillow"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"homeType"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"APARTMENT"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every listing that carried a price was two bedrooms or more and $2,500 or less. Some rows are apartment buildings rather than units, with &lt;code&gt;price&lt;/code&gt;, &lt;code&gt;beds&lt;/code&gt; and &lt;code&gt;baths&lt;/code&gt; as &lt;code&gt;null&lt;/code&gt; and only an address, so the agent has to skip those or open them. The three calls returned byte-identical payloads within a minute, which reads like a short server-side cache. The property tool takes the listing URL from the search result, so the "pull the full record" half of the task is one more call, 33 fields.&lt;/p&gt;

&lt;p&gt;The payload is the largest of the working servers, 159 KB for the page. That is the whole listing object per rental. If the agent only needs price and address it is reading more than it uses, and there is no field selector on the search tool.&lt;/p&gt;

&lt;p&gt;Billing is one call per page whatever the page returns, 200 calls a month free and renewing, then $59 a month for 40,000 calls. For this agent that is one call per search plus one per record you open.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Apify, the afanasenko Zillow actor
&lt;/h2&gt;

&lt;p&gt;Apify exposes any actor in its store as an MCP tool through one hosted endpoint. You pick the actors in the URL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;claude mcp add &lt;span class="nt"&gt;--transport&lt;/span&gt; http apify-zillow &lt;span class="s2"&gt;"https://mcp.apify.com/?tools=afanasenko/zillow-mcp-server"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$APIFY_TOKEN&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://apify.com/afanasenko/zillow-mcp-server" rel="noopener noreferrer"&gt;This actor&lt;/a&gt; has three tools, search by ZIP or place, search by any Zillow URL, and lookup by zpid. Denver rentals went in as a Zillow rentals URL. It returned 15 rentals with 77 fields each, the richest per-listing record of the set, 42 KB, in 6.7 to 13.4 seconds. The first fields on a Denver result were price, status, home type, coordinates, a description with the floor plans and the listing URL, and the tool's own description promises agent contact, Zestimates, HOA, tax and price history further down the record. Each call is a fresh actor run on Apify's side, so the latency floor is the run spin-up. On a ZIP search the same actor took 25 and 45 seconds for two calls and the third ran into a 120 second wall and errored.&lt;/p&gt;

&lt;p&gt;Cost is Apify platform usage per run, and it differs a lot between actors. Six afanasenko searches across two scenarios consumed $5.25 of a $5 free month, about 87 cents a search, while three maxcopell two-step searches cost 28 cents together, about 9 cents each. The free tier is a demo for the first actor and a month of light use for the second. The afanasenko actor caps at 15 results per call in this configuration, so a 41-listing page is three calls.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Apify, the maxcopell Zillow scraper
&lt;/h2&gt;

&lt;p&gt;Same endpoint, different actor, and a different shape. &lt;a href="https://apify.com/maxcopell/zillow-scraper" rel="noopener noreferrer"&gt;&lt;code&gt;maxcopell/zillow-scraper&lt;/code&gt;&lt;/a&gt; takes a Zillow search URL that must contain &lt;code&gt;searchQueryState&lt;/code&gt;, plus an extraction method, and returns run metadata, not listings. The listings land in a dataset that you fetch with the &lt;code&gt;get-dataset-items&lt;/code&gt; tool in a second call, and the id for that call sits at &lt;code&gt;storages.datasets.default.id&lt;/code&gt; in the first response. Our first attempt read the wrong field and the second call failed three times. With the right path the pair of calls completed three out of three in 12.4 to 14.5 seconds and returned 40 rentals with 17 fields each, 168 KB, the most listings per search of any server here. An agent using this actor has to know the two-step protocol, and the first response gives it nothing to reason about except a status line that says "scraped 40 items".&lt;/p&gt;

&lt;h2&gt;
  
  
  4. APIllow
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://apillow.co/" rel="noopener noreferrer"&gt;A Zillow-only vendor&lt;/a&gt; with a PyPI package. The README's &lt;code&gt;uvx apillow-mcp&lt;/code&gt; crashes on a current Python MCP SDK because the package imports &lt;code&gt;FastMCP&lt;/code&gt; from a location that SDK 2.x renamed. Pin the SDK and it starts:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;claude mcp add apillow &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;APILLOW_API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$APILLOW_API_KEY&lt;/span&gt; &lt;span class="nt"&gt;--&lt;/span&gt; uvx &lt;span class="nt"&gt;--with&lt;/span&gt; &lt;span class="s2"&gt;"mcp&amp;lt;2"&lt;/span&gt; apillow-mcp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ten tools, seven for data (search by city, ZIP, zpid, URL, address, batch, address check). The Denver call was &lt;code&gt;search_properties&lt;/code&gt; with &lt;code&gt;type: for_rent&lt;/code&gt;. It answered three out of three in 7 to 17 seconds with &lt;code&gt;status: complete&lt;/code&gt; and five properties. The prices were $525,000 and $975,000, which are sale prices, and the records had &lt;code&gt;last_sold_price&lt;/code&gt; fields, so the rental filter did not apply and the agent got five houses for sale. The server submits a job and polls, which is where the time goes, and one earlier search hit the vendor's own 120 second job timeout.&lt;/p&gt;

&lt;p&gt;Fifty properties a month are free, then $9.99 for 3,333. It bills per property returned, including the five wrong ones. After the allowance it keeps answering &lt;code&gt;200&lt;/code&gt; with &lt;code&gt;{"error": "Rate limit or quota exceeded"}&lt;/code&gt; in the body.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. @striderlabs/mcp-zillow
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/markswendsen-code/mcp-zillow" rel="noopener noreferrer"&gt;An open-source server&lt;/a&gt; with Playwright and a stealth plugin, no key. &lt;code&gt;npx -y @striderlabs/mcp-zillow&lt;/code&gt; fails because the npm package ships &lt;code&gt;src/index.ts&lt;/code&gt; and no &lt;code&gt;dist&lt;/code&gt;. Cloned and built it starts in under a second with five tools, &lt;code&gt;search_homes&lt;/code&gt;, &lt;code&gt;search_rentals&lt;/code&gt;, &lt;code&gt;get_listing&lt;/code&gt;, &lt;code&gt;get_estimates&lt;/code&gt;, &lt;code&gt;save_home&lt;/code&gt;. &lt;code&gt;search_rentals&lt;/code&gt; for Denver returned in 3 to 5 seconds with &lt;code&gt;total_found: 0&lt;/code&gt; all three times, and the same for sales in Phoenix and a Miami Beach ZIP. Zillow is serving its headless Chromium an empty results page, so the server is free and so is its output.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. chrischall/zillow-mcp
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://github.com/chrischall/zillow-mcp" rel="noopener noreferrer"&gt;most downloaded Zillow MCP package&lt;/a&gt; on npm, about 1,400 a month, with 20 tools including mortgage math and saved searches. It is in the table as six failures because it cannot run where Claude Code runs. Every tool goes through a WebSocket bridge to a browser extension that uses your logged-in zillow.com session, and without a signed-in Chrome next to the client every call fails with "no confirmed browser session". Six of six here. If you only ever run Claude Desktop on the laptop where you browse Zillow, it may be the most capable free option. For anything headless it is not an option.&lt;/p&gt;

&lt;h2&gt;
  
  
  The build-it-yourself path
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/ZacharyHampton/HomeHarvest" rel="noopener noreferrer"&gt;HomeHarvest&lt;/a&gt; is a 739-star Python library that scrapes Zillow, Realtor.com and Redfin into a DataFrame, and it is the usual answer when someone asks how to get Zillow data without a vendor. It is not an MCP server. Wrapping it in one is an afternoon with the Python SDK, and then the anti-bot problem the striderlabs server hit is yours. That is the trade, and it is the same trade every hosted server above is charging for.&lt;/p&gt;

&lt;h2&gt;
  
  
  What we kept
&lt;/h2&gt;

&lt;p&gt;For the rental agent, HasData. Place name in, 41 rentals out, one call, every time, and the property record is the same key and one more call. The Apify actor is the one to keep around for the record depth, 77 fields per listing, when the agent already knows what it wants and can afford seven seconds and a metered run per lookup. APIllow needs a fix to its rental filter before it belongs in a rental agent. The two open-source servers that show up next to these in the catalogs are, today, a package that does not install and a package that installs and returns nothing.&lt;/p&gt;

&lt;p&gt;All of it is one afternoon's measurement from one machine, three calls per server, and vendors change. Rerun before you commit.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>mcp</category>
      <category>webscraping</category>
      <category>claude</category>
    </item>
  </channel>
</rss>
