Choose a Google or Bing result source by testing the task your application performs. Use the same query, country and language, preserve the sampling time, and compare useful URLs and result features. A different result set does not prove that one engine is more accurate or reaches a more valuable audience.
Define what counts as a useful result
For a technical research task, a useful result might be an official documentation page that answers a specific question. For rank monitoring, it might be the exact observed ordering for an engine and market. Define that requirement before comparing the two engines. Do not substitute unsourced market-share, age-profile or industry-strength claims for a task-level test.
| Control | Reason |
|---|---|
| Query string | Different formulations change the task |
| Country and language | Locale differences can change results |
| Requested result scope | Compare the same operation, not web results against a different vertical |
| Sample timestamps | Sequential samples are not a simultaneous search snapshot |
| Judgment rule | URL overlap is different from answer usefulness |
Normalize the two response envelopes
SearchCans exposes both sources through POST /api/v1/search using t: google or t: bing. Bing Search API and Google Search API document the first-party integration. Treat this as access through SearchCans, not a claim of using a current direct Microsoft developer API. The example compares the URL sets while preserving both raw engine choices.
import os
import requests
from datetime import datetime, timezone
from urllib.parse import urlsplit, urldefrag
def organic(envelope):
if envelope.get("code") != 0:
raise ValueError("Search business error")
data = envelope.get("data")
if not isinstance(data, dict) or not isinstance(data.get("organic"), list):
raise ValueError("Expected data.organic array")
return [row for row in data["organic"] if isinstance(row, dict)
and isinstance(row.get("link"), str)
and urlsplit(row["link"]).scheme == "https"
and urlsplit(row["link"]).hostname
and not urlsplit(row["link"]).username]
def call(path, payload, session=requests, timeout=40):
response = session.post("https://www.searchcans.com/api/v1/" + path,
headers={"Authorization": "Bearer " + os.environ["SEARCHCANS_API_KEY"]},
json=payload, timeout=timeout)
response.raise_for_status()
envelope = response.json()
if envelope.get("code") != 0 or not isinstance(envelope.get("data"), dict):
raise ValueError("Business or response-schema error")
return envelope
def compare_engines(query, session=requests):
samples = {}
for engine in ("google", "bing"):
envelope = call("search", {"t":engine, "s":query,
"country":"us", "language":"en", "d":30000}, session)
samples[engine] = {urldefrag(row["link"])[0] for row in organic(envelope)}
both = samples["google"] & samples["bing"]
union = samples["google"] | samples["bing"]
return {"query":query, "country":"us", "language":"en",
"sampled_at":datetime.now(timezone.utc).isoformat(),
"google_urls":sorted(samples["google"]), "bing_urls":sorted(samples["bing"]),
"intersection":sorted(both), "jaccard":len(both)/len(union) if union else None}
Interpret the intersection without inventing a winner
For a synthetic fixture where Google returns A and B and Bing returns B and C, the intersection contains B and Jaccard overlap is one third. That describes agreement between those two sets. It does not say which page answers the user, whether omitted pages are indexed, or whether either engine is complete. Two empty sets return no overlap score instead of a misleading perfect match.
A live paired sample is useful only when both calls complete with their requested inputs. If one engine fails, retain that error and repeat the pair before making a coverage comparison. Never combine one fresh engine response with an older response and call the pair a current benchmark.
Make the selection task-specific
Label expected answers or sources, then inspect the returned pages. Record useful results, duplicates, errors and features your application actually consumes. If one engine is an optional fallback, test whether its additional URLs add evidence rather than treating any larger set as an improvement.
Use the controlled query workflow to repeat the comparison. the Bing API migration guide owns migration mechanics and the Bing alternatives guide owns supplier selection. This page does not repeat either task or publish an unsupported engine-to-engine performance claim.