Bing Search API replacement: fix calls to api.bing.microsoft.com
Microsoft shut down the Bing Search APIs on 11 August 2025, so requests to api.bing.microsoft.com/v7.0/search no longer work. ContextFetch serves a Bing v7-compatible web search route at https://api.contextfetch.dev/bing/v7.0/search: same query parameters, same Ocp-Apim-Subscription-Key header, same SearchResponse JSON with webPages.value. Change the URL and the key and your parsing code keeps working. It returns web results only, at $1 per 1,000 searches.
1. Why your Bing code stopped working
Microsoft retired the Bing Search APIs, including Bing Web Search v7 and Bing Custom Search, on 11 August 2025. Its lifecycle notice says existing instances were decommissioned completely and no new signups are accepted: Bing Search APIs retiring on August 11, 2025.
So any code that still sends requests to https://api.bing.microsoft.com/v7.0/search fails, whether it is a script built from Microsoft's Python quickstart, a LangChain tool, or a cron job nobody has touched in years. The fix does not need a new client library. Point the same request at a server that still speaks the v7 format.
2. Get a ContextFetch key
A single POST gives you a free key loaded with $2.50, which covers 2,500 web searches. No account form is involved, and each network can claim one free key. Put it in CONTEXTFETCH_API_KEY, which is where the program below looks for it.
To just poke at the route first, you can leave the key header off entirely: keyless calls are allowed 25 times per IP address per UTC day.
curl -X POST https://api.contextfetch.dev/v1/keys/free# {"apiKey": "cf_live_...", "balance_usd": 2.5}export CONTEXTFETCH_API_KEY="cf_live_..."3. Change the endpoint and the key
In code based on Microsoft's quickstart, two values change: search_url and the key. The header name stays Ocp-Apim-Subscription-Key, so the requests.get call and every line that reads webPages.value stay as they are.
The route accepts q, count (up to 50), offset for paging, mkt such as en-US, and freshness as Day, Week, Month or a YYYY-MM-DD..YYYY-MM-DD range. Each page in webPages.value carries id, name, url, displayUrl, snippet, dateLastCrawled, language and isFamilyFriendly, and rankingResponse.mainline.items lists them in order, as Bing's did.
import osimport requests # before: retired on 11 August 2025# search_url = "https://api.bing.microsoft.com/v7.0/search"# subscription_key = os.environ["BING_SEARCH_V7_SUBSCRIPTION_KEY"] # aftersearch_url = "https://api.contextfetch.dev/bing/v7.0/search"subscription_key = os.environ["CONTEXTFETCH_API_KEY"] headers = {"Ocp-Apim-Subscription-Key": subscription_key}params = {"q": "python requests timeout", "textDecorations": True, "textFormat": "HTML"}response = requests.get(search_url, headers=headers, params=params)response.raise_for_status()search_results = response.json()4. LangChain's BingSearchAPIWrapper
BingSearchAPIWrapper in langchain_community.utilities takes bing_subscription_key and bing_search_url (or the BING_SUBSCRIPTION_KEY and BING_SEARCH_URL environment variables). Its default URL is the retired Bing endpoint, so set bing_search_url to the ContextFetch route and pass your ContextFetch key. run() and results() then work unchanged; we checked both against langchain-community 0.4.2.
One caution: langchain-community's maintainers have announced that the package is being sunset, and importing it now prints a deprecation warning. The wrapper still installs and works, but for new code a plain requests call like the one above is the more durable choice.
import osfrom langchain_community.utilities import BingSearchAPIWrapper search = BingSearchAPIWrapper( bing_subscription_key=os.environ["CONTEXTFETCH_API_KEY"], bing_search_url="https://api.contextfetch.dev/bing/v7.0/search", k=3,)print(search.results("python requests timeout", 3)) # or set BING_SEARCH_URL and BING_SUBSCRIPTION_KEY and call BingSearchAPIWrapper()5. What is different from Bing
- Only web results. There are no news, image, video, entity, autosuggest or spell check routes, and the response has no
news,imagesorvideossections. - Snippets are plain text.
textDecorationsandtextFormat=HTMLare accepted and ignored, so there are no hit-highlight markers to strip. dateLastCrawledis a date for the page, sometimes its publication date rather than a crawl time, so do not treat it as an exact crawl timestamp.webPages.webSearchUrllinks to the ContextFetch playground instead of bing.com.
6. Cost
A request with count of 25 or fewer is one search at $1 per 1,000, or $0.001 each. Asking for more raises the price by another $1 per 1,000 for each extra block of 25, so count=50 costs $0.002. Every billable response includes X-Cost-USD and X-Balance-USD headers, which makes the spend easy to log. See pricing for top-ups.
The complete code
Python, runnable as is with CONTEXTFETCH_API_KEY set. Install first: requests. We ran it against the live API; the output below is what it printed.
import os import requests # The only two lines that changed from Microsoft's quickstart:search_url = "https://api.contextfetch.dev/bing/v7.0/search"subscription_key = os.environ["CONTEXTFETCH_API_KEY"] headers = {"Ocp-Apim-Subscription-Key": subscription_key}params = {"q": "python requests timeout", "count": 3, "mkt": "en-US"} response = requests.get(search_url, headers=headers, params=params, timeout=30)response.raise_for_status()search_results = response.json() print(search_results["_type"], "for", repr(search_results["queryContext"]["originalQuery"]))for page in search_results["webPages"]["value"]: print(f"- {page['name']}\n {page['url']}\n {page['snippet'][:160]}") SearchResponse for 'python requests timeout'
- Python Requests Timeout: A Complete Guide for Developers
https://python-requests.org/python-requests-timeout/
When working with APIs, web scraping, or any online data retrieval in Python, handling timeouts correctly is critical. Without proper timeout settings, your pro
- A Complete Guide to Timeouts in Python | Better Stack Community
https://betterstack.com/community/guides/scaling-python/python-timeouts/
Back to Scaling Python applications guides Python Stanley Ulili Updated on March 4, 2025 Why you need timeouts in Python HTTP request timeouts Database operatio
- Timeout for Python requests.get() entire response - Stack Overflow
https://stackoverflow.com/questions/21965484/timeout-for-python-requests-get-entire-response
timeout is not a time limit on the entire response download; rather, an exception is raised if the server has not issued a response for timeout ...The same call with curl
The raw HTTP request, and the response it returned (long text fields and lists shortened).
curl -s "https://api.contextfetch.dev/bing/v7.0/search?q=python+requests+timeout&count=3&mkt=en-US" \ -H "Ocp-Apim-Subscription-Key: $CONTEXTFETCH_API_KEY"{
"_type": "SearchResponse",
"queryContext": {
"originalQuery": "python requests timeout"
},
"webPages": {
"webSearchUrl": "https://contextfetch.dev/playground?q=python+requests+timeout",
"totalEstimatedMatches": 3,
"value": [
{
"id": "https://api.contextfetch.dev/bing/v7.0/search#WebPages.0",
"name": "Python Requests Timeout: A Complete Guide for Developers",
"url": "https://python-requests.org/python-requests-timeout/",
"displayUrl": "python-requests.org/python-requests-timeout/",
"snippet": "When working with APIs, web scraping, or any online data retrieval in Python, handling timeouts correctly is critical. Without proper timeout settings, your program may hang indefinitely, consume system resources, or become unresponsive. In this comprehensive guide, we’ll explore…",
"dateLastCrawled": "2025-11-13T00:00:00.0000000Z",
"language": "en",
"isFamilyFriendly": true
},
{
"id": "https://api.contextfetch.dev/bing/v7.0/search#WebPages.1",
"name": "A Complete Guide to Timeouts in Python | Better Stack Community",
"url": "https://betterstack.com/community/guides/scaling-python/python-timeouts/",
"displayUrl": "betterstack.com/community/guides/scaling-python/python-timeouts/",
"snippet": "Back to Scaling Python applications guides Python Stanley Ulili Updated on March 4, 2025 Why you need timeouts in Python HTTP request timeouts Database operation timeouts Timeouts in asynchronous programming How to choose a timeout value Final thoughts Every Python application in…",
"dateLastCrawled": "2025-03-04T00:00:00.0000000Z",
"language": "en",
"isFamilyFriendly": true
},
{
"id": "https://api.contextfetch.dev/bing/v7.0/search#WebPages.2",
"name": "Timeout for Python requests.get() entire response - Stack Overflow",
"url": "https://stackoverflow.com/questions/21965484/timeout-for-python-requests-get-entire-response",
"displayUrl": "stackoverflow.com/questions/21965484/timeout-for-python-requests-get-entire-response",
"snippet": "timeout is not a time limit on the entire response download; rather, an exception is raised if the server has not issued a response for timeout ...",
"dateLastCrawled": "2014-02-23T00:00:00.0000000Z",
"language": "en",
"isFamilyFriendly": true
}
]
},
"rankingResponse": {
"mainline": {
"items": [
{
"answerType": "WebPages",
"resultIndex": 0,
"value": {
"id": "https://api.contextfetch.dev/bing/v7.0/search#WebPages.0"
}
},
{
"answerType": "WebPages",
"resultIndex": 1,
"value": {
"id": "https://api.contextfetch.dev/bing/v7.0/search#WebPages.1"
}
},
{
"answerType": "WebPages",
"resultIndex": 2,
"value": {
"id": "https://api.contextfetch.dev/bing/v7.0/search#WebPages.2"
}
}
]
}
}
}