# Bing Search API Replacement Scraper (`devilscrapes/bing-search-scraper`) Actor

Bing SERP scraper and Bing Search API alternative — returns organic results (title, URL, displayed URL, snippet, position) for any query, export to JSON or CSV. A drop-in replacement for the deprecated Bing Search API for SEO, brand monitoring, and AI agents.

- **URL**: https://apify.com/devilscrapes/bing-search-scraper.md
- **Developed by:** [DevilScrapes](https://apify.com/devilscrapes) (community)
- **Categories:** SEO tools
- **Stats:** 5 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

<img src="https://apify.com/.actor/icon.svg" width="160" alt="Bing Search Scraper — Bing Search API Replacement" />

## Bing Search API Replacement — Bing Search Scraper

*We do the dirty work so your dataset stays clean.* 😈

**$1.20 / 1,000 SERP rows — the drop-in replacement for the retired Bing Search API.** Microsoft shut down the official Bing Search API on August 11, 2025, stranding SEO agencies, brand-monitoring tools, AI search agents, and RAG pipelines. This Actor is the successor: residential-proxy-backed, locale-aware, browser-fingerprint-rotating, and priced for high-volume workloads at a fraction of SerpApi or DataForSEO.

### 🎯 What this scrapes

Bing's public `www.bing.com/search` SERP — the same page any browser renders for a typed query. Per query the Actor:

1. Issues `GET https://www.bing.com/search?q=<query>&cc=<country>&setlang=<language>&count=10&first=<offset>` via `curl-cffi` with rotating browser fingerprints.
2. Parses every `<li class="b_algo">` block with `parsel` to extract title, snippet, displayed URL, and the redirect-wrapped href.
3. **Decodes the Bing redirect**: `bing.com/ck/a?...&u=a1<base64url>` → canonical destination URL. No Bing redirect wrappers ever reach your dataset.
4. Paginates via `&first=0,10,20,...` until `maxResultsPerQuery` rows are emitted or the page returns zero organic blocks.

Each output row carries:

| Field | Type | Description |
|---|---|---|
| `query` | string | The input search query that produced this row |
| `position` | integer | 1-indexed organic rank within the query (across pages) |
| `title` | string | Result headline text |
| `url` | string | Canonical destination URL (decoded from `bing.com/ck/a`) |
| `displayed_url` | string | null | Breadcrumb-style URL as Bing renders it |
| `snippet` | string | null | Description excerpt shown under the result |
| `country` | string | ISO-3166-1 alpha-2 country passed in (`cc=`) |
| `language` | string | ISO-639-1 language passed in (`setlang=`) |
| `scraped_at` | string | ISO 8601 UTC timestamp of row creation |

### 🔥 Features

- **Drop-in Bing Search API replacement** — same shape (query → list of organic results), no Microsoft API key required.
- **Locale-aware** — `cc=` / `setlang=` flow straight through to Bing; one Actor covers every market from US to JP to DE.
- **URL decoded** — Bing redirect wrappers (`bing.com/ck/a?...`) are always decoded to the canonical destination URL. Your dataset joins cleanly against any URL-keyed dataset.
- **We rotate browser fingerprints** — `curl-cffi` impersonates Chrome 131, Chrome 124, and Firefox 147 TLS+H2 fingerprints per page. Bing sees real-browser handshakes, not Python.
- **We rotate residential proxies** — Apify Proxy is on by default. Bing weights residential exits strongly over datacenter IPs, especially for paginated bursts. On every block we rotate session\_id and exit IP.
- **We retry with exponential backoff** — 429 / 503 responses trigger a 2 s → 4 s → 8 s → 16 s → 30 s retry ladder, honouring `Retry-After` headers, up to 5 attempts per page.
- **Per-query isolation** — one query failing (zero results, network hiccup) does not abort the run. Remaining queries continue and the run surfaces a partial-success status message.
- **Early-stop on empty page** — we stop paginating when Bing stops returning organic blocks, instead of hammering empty pages.
- **Pydantic v2 validation** — input and every output row are model-validated. Invalid input fails fast with a clear message before any network call.

### 💡 Use cases

- **Bing Search API migration** — Microsoft retired the official endpoint on August 11, 2025. This Actor is the drop-in replacement for client reports, AI search agents, and competitive intelligence pipelines that depended on it.
- **SEO rank tracking** — schedule weekly runs across your target queries, write to a named dataset, and chart `position` over time per keyword and locale.
- **Brand monitoring** — watch the top 30 organic results for branded queries (your brand, competitors, key product names) and alert on new entrants.
- **AI search agents and RAG pipelines** — feed live SERP context into LLM agents. Bing diversifies your retrieval from Google: more forums, more long-tail, more long-form blogs.
- **Multi-locale SERP comparison** — pass the same query with different `cc=` / `setlang=` values to compare what Bing shows in the US vs UK vs DE vs JP.
- **Content-gap analysis** — pull the top 30 results for queries you want to rank for and reverse-engineer what content Bing rewards.
- **Quality-assurance for Bing Webmaster Tools data** — cross-check the impressions and positions Bing reports against what the live SERP actually shows.
- **Bing SERP data for LangChain and LlamaIndex agents** — replaces the now-dead `BingSearchAPIWrapper` and `BingToolSpec` integrations that called the retired API.

### ⚙️ How to use it

1. Open the Actor input form.
2. Enter at least one query in **Queries** (one row per `query × organic result`).
3. (Optional) Set **Country** — ISO-3166-1 alpha-2 (default `US`; common: `GB`, `DE`, `FR`, `JP`, `BR`).
4. (Optional) Set **Language** — ISO-639-1 (default `en`).
5. (Optional) Set **Max results per query** — 1 to 100 (default 30; pagination quality degrades past page 5–7).
6. Leave **Use Apify Proxy** on. Bing weights residential exits strongly over datacenter IPs.
7. Click **Start**. Results stream into the default dataset.

#### Quick examples

**One query, first page only (the QA fixture):**

```json
{
  "queries": ["devilscrapes apify"],
  "country": "US",
  "language": "en",
  "maxResultsPerQuery": 10,
  "useProxy": true
}
```

**Multi-query rank tracking (US, top 30 each):**

```json
{
  "queries": [
    "best web scraping tool",
    "apify alternatives",
    "bing search api replacement"
  ],
  "country": "US",
  "language": "en",
  "maxResultsPerQuery": 30,
  "useProxy": true
}
```

**Multi-locale brand monitoring (top 20, three markets):**

```json
{
  "queries": ["devilscrapes"],
  "country": "GB",
  "language": "en",
  "maxResultsPerQuery": 20,
  "useProxy": true
}
```

Run three times, swapping `country` / `language`, and merge datasets on your side.

### 📥 Input

| Field | Type | Required | Default | Description |
|---|---|---|---|---|
| `queries` | array of strings | yes | — | Search queries to run. One dataset row per `query × organic result`. At least one required. |
| `country` | string | no | `US` | ISO-3166-1 alpha-2 country passed to Bing as `cc=`. |
| `language` | string | no | `en` | ISO-639-1 language passed to Bing as `setlang=`. |
| `maxResultsPerQuery` | integer 1..100 | no | `30` | Upper bound on organic results per query. Paginated in steps of 10. |
| `useProxy` | boolean | no | `true` | Route via Apify Proxy (residential group). Strongly recommended. |

### 📤 Output

One dataset row per `query × organic result`. Example record:

```json
{
  "query": "bing search api replacement",
  "position": 1,
  "title": "DevilScrapes — Bing Search Scraper",
  "url": "https://apify.com/DevilScrapes/bing-search-scraper",
  "displayed_url": "https://apify.com › DevilScrapes › bing-search-scraper",
  "snippet": "Drop-in replacement for the retired Bing Search API. Organic results for any query, locale-aware, residential-proxy-backed.",
  "country": "US",
  "language": "en",
  "scraped_at": "2026-05-16T13:40:00.000Z"
}
```

Download as JSON, CSV, Excel, or XML from the **Export** button on the run page.

### 💰 Pricing

Pay-Per-Event (PPE):

| Event | Rate (USD) | Trigger |
|---|---|---|
| `actor-start` | $0.20 | Once per Actor run at boot |
| `result-row` | $0.001 | Per organic SERP row pushed |

A typical run (10 queries × 30 results = 300 rows) costs **~$0.35**. Per-1,000-row extrapolation: **$1.20**. Priced below typical Google SERP scrapers to capture teams migrating from the retired Bing Search API. **You pay only for results that land** — no data, no charge beyond the $0.05 start fee.

### 🚧 Limitations

- **Organic web results only** — People-Also-Ask boxes, Related Searches, news, images, videos, maps, and Bing's local pack are out of scope for v1.
- **Featured snippets are not extracted as a separate field** — when Bing's featured snippet sits inside a `<li class="b_algo">` block it appears as a regular row. No `is_featured` flag in v1.
- **Up to 100 results per query** — `maxResultsPerQuery` is capped at 100. Past page 10 Bing's organic results become unreliable.
- **No JavaScript rendering** — we hit server-rendered HTML directly. If Bing migrates to a fully client-rendered SERP, a Camoufox path would be needed.
- **Country / language are passed to Bing, not validated** — `cc=` / `setlang=` are interpolated raw into the URL. An unrecognized value will silently return default-locale results. Use standard ISO codes.
- **No historical tracking built in** — every run is a fresh snapshot. Schedule runs and export to your own storage (BigQuery, S3, named Apify dataset) to build a time series. Apify default run-scoped storage is purged after 7 days on the free plan.

### ❓ FAQ

**Why does this exist? Isn't there an official Bing Search API?**
Microsoft retired the Bing Search API on August 11, 2025. There is no longer an official programmatic endpoint for Bing organic results. The replacement Microsoft offers — "Grounding with Bing Search" inside Azure AI — is locked to a single LLM workflow and costs orders of magnitude more per call. This Actor hits the public SERP that any browser hits.

**What does "bing search api replacement" mean in practice?**
The retired API returned a JSON payload of organic results for a query. This Actor returns the same shape: query in, list of `{position, title, url, snippet, ...}` rows out. Migration means swapping an API call for an Apify Actor run. The output schema is stable across versions.

**Is this allowed?**
The Actor sends well-formed HTTP requests to a public, unauthenticated SERP endpoint and parses the publicly visible HTML. It respects HTTP retry semantics (429 / 503 / Retry-After). Your obligation as the user is to comply with Bing's Terms of Service in your jurisdiction. This Actor does not bypass any login, paywall, or authentication mechanism.

**Why does the Actor rotate browser fingerprints?**
`curl-cffi` impersonates real browser TLS+H2 fingerprints. Rotating across Chrome 131, Chrome 124, and Firefox 147 per page reduces correlation between consecutive requests — which lowers the chance Bing flags a paginated burst as automated traffic. We handle the blocks so you don't have to.

**Why is `position` 1-indexed?**
That is how every SEO tool, rank tracker, and BI dashboard counts. Position 1 = the first organic result. It drops straight into spreadsheets and databases without an off-by-one fix.

**Why are URLs decoded? Can I get the raw `bing.com/ck/a` redirect?**
v1 always decodes. The redirect wrapper is a click-tracking detail; it adds no information your downstream workflow can use. Canonical URLs join cleanly with any other dataset keyed on URL.

**Does this work for non-English locales?**
Yes. `setlang=de` / `setlang=ja` / `setlang=fr` all flow through to Bing. The parser is structural (`li.b_algo` blocks); it does not depend on English text patterns.

**What about People-Also-Ask (PAA) boxes?**
Out of scope for v1. If there is demand, v2 will add an opt-in `extractPaa: true` input field that adds a separate `kind: "paa"` row per question.

**How do I use this as a drop-in for LangChain's `BingSearchAPIWrapper`?**
Run the Actor with your query, export the dataset, and pass the `url` + `snippet` fields into your chain's retrieval step. The JSON output shape is close to what the dead API returned. A full cookbook migration example is in progress for Dev.to.

**Do I need the Apify Proxy?**
Strongly recommended. Bing favours residential IPs over datacenter IPs, especially for paginated bursts. The default is ON. Turn it off only if you have your own proxy stack.

### 💬 Your feedback

Found a parser that broke after a Bing SERP markup change? Want a new feature (PAA boxes, news vertical, location targeting)? Open an issue on the Actor's Apify Store page or reach us at [apify.com/DevilScrapes](https://apify.com/DevilScrapes). We monitor publish-day QA failures and ship patches the same week.

# Actor input Schema

## `queries` (type: `array`):

List of search queries. One dataset row is emitted per (query × organic result). At least one query is required.

## `country` (type: `string`):

ISO-3166-1 alpha-2 country code passed to Bing as <code>cc=</code> (e.g. <code>US</code>, <code>GB</code>, <code>DE</code>, <code>JP</code>).

## `language` (type: `string`):

ISO-639-1 language code passed to Bing as <code>setlang=</code> (e.g. <code>en</code>, <code>de</code>, <code>fr</code>, <code>ja</code>).

## `maxResultsPerQuery` (type: `integer`):

Upper bound on organic results returned per query. Bing serves 10 organic results per page; the scraper paginates via <code>\&first=0,10,20...</code> until this limit is reached or a page returns zero results.

## `useProxy` (type: `boolean`):

Route requests through Apify Proxy (<code>BUYPROXIES94952</code>, a static US datacenter pack). Recommended ON. Note that Bing weights residential exits more favourably than datacenter IPs, so select a RESIDENTIAL group here if your plan has one.

## Actor input object example

```json
{
  "queries": [
    "apify web scraping"
  ],
  "country": "US",
  "language": "en",
  "maxResultsPerQuery": 30,
  "useProxy": true
}
```

# Actor output Schema

## `datasetItems` (type: `string`):

All dataset items as JSON.

## `datasetItemsCsv` (type: `string`):

Same data exported to CSV.

## `datasetView` (type: `string`):

Open the run dataset in the Console.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "queries": [
        "apify web scraping"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("devilscrapes/bing-search-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "queries": ["apify web scraping"] }

# Run the Actor and wait for it to finish
run = client.actor("devilscrapes/bing-search-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "queries": [
    "apify web scraping"
  ]
}' |
apify call devilscrapes/bing-search-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,devilscrapes/bing-search-scraper"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/baD0ehnF0bHNpqW3Q/builds/fhJTI6mZjQazYlHGr/openapi.json
