# Bing Search Results Scraper (`automation-lab/bing-search-results-scraper`) Actor

Export ranked organic Bing results by keyword and market for SEO rank tracking, domain visibility audits, and competitor research.

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

## Pricing

from $1.38 / 1,000 item extracteds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## Bing Search Results Scraper

Export **Bing search results** as clean, ranked organic records for recurring SEO rank tracking, competitor-result research, and domain visibility audits. Supply one or many queries and receive titles, resolved destination URLs, domains, snippets, organic positions, market settings, retrieval timestamps, and exact Bing source URLs.

The Actor uses Bing's public server-rendered search surface with a lightweight RSS fallback. It does not require a Microsoft API key, browser, or user account.

### What can you do with this Bing search scraper?

- Track where pages appear for a recurring keyword set.
- Compare domains ranking across related search terms.
- Audit whether a brand or product appears in Bing results.
- Export result titles and snippets for content-gap research.
- Feed ranked rows into a spreadsheet, database, dashboard, or agent.
- Schedule the same input and compare datasets over time.

Each row retains its originating query and one-based organic position. The Actor produces snapshots; it does not claim to maintain rank history inside one run.

### Who is it for?

**SEO specialists** can collect Bing positions for keyword portfolios without manually copying result pages.

**Content and growth teams** can inspect the pages and messaging Bing surfaces for commercial topics.

**Competitive-intelligence teams** can compare recurring result snapshots and detect newly visible domains.

**Developers and data teams** can integrate structured Bing results through the Apify API, webhooks, schedules, Make, Zapier, or MCP.

### Why use this Actor?

Bing results are normalized into one stable dataset shape rather than raw HTML. Destination redirects are resolved where Bing exposes them, duplicate URLs are removed per query, and limits are enforced before result charges.

The Actor also records:

- the requested Bing market;
- the SafeSearch level;
- the result page number;
- the exact source URL;
- the retrieval timestamp.

This evidence makes repeated exports easier to compare and audit.

### Extracted Bing result fields

| Field | Type | Meaning |
| --- | --- | --- |
| `query` | string | Search term that produced the row |
| `position` | integer | One-based organic position for that query |
| `title` | string | Result title shown by Bing |
| `url` | string | Resolved destination URL |
| `domain` | string | Destination hostname without leading `www` |
| `snippet` | string or null | Bing's result description, when available |
| `page` | integer | One-based Bing result page |
| `market` | string | Language-country market used for the request |
| `safeSearch` | string | Applied SafeSearch level |
| `sourceUrl` | string | Exact Bing page or RSS URL fetched |
| `retrievedAt` | ISO date-time | Time the source page was retrieved |

Only organic web results are emitted. Ads, image cards, maps, news modules, and People Also Ask panels are not represented as organic rows.

### How to scrape Bing search results

1. Open the Actor in Apify Console.
2. Add one or more terms to **Search queries**.
3. Choose the maximum results per query and total run limit.
4. Select the Bing market and SafeSearch level.
5. Click **Start**.
6. Open the default dataset to download JSON, CSV, Excel, XML, or another supported format.

Start with 10–20 results per query when validating a new recurring workflow.

### Input parameters

#### `queries`

Required list of 1–50 non-empty search terms. Duplicate terms are rejected so the same query is not charged twice accidentally. Each term can contain up to 300 characters.

Examples:

```json
["bing search api", "serp api", "keyword research tool"]
```

Bing operators can be included, but Bing may interpret or ignore operators differently by market and over time.

#### `maxResultsPerQuery`

Maximum accepted organic rows for each query. Allowed range: 1–100. This is a cap, not a guarantee; Bing can expose fewer unique organic results.

#### `maxItems`

Run-wide cap across all queries. Allowed range: 1–1,000. The Actor stops accepting results as soon as this cap is reached.

#### `market`

Supported markets include `en-US`, `en-GB`, `en-CA`, `en-AU`, `de-DE`, `fr-FR`, `es-ES`, `it-IT`, `nl-NL`, and `pt-BR`.

The market influences language and localization, but rankings can still vary by time, index state, and Bing's own personalization logic.

#### `safeSearch`

Choose `Off`, `Moderate`, or `Strict`. The default is `Moderate`.

### Example input: one keyword

```json
{
  "queries": ["bing search api"],
  "maxResultsPerQuery": 10,
  "maxItems": 10,
  "market": "en-US",
  "safeSearch": "Moderate"
}
```

### Example input: competitor workflow

```json
{
  "queries": ["serp api", "keyword research tool", "Bing rank tracking"],
  "maxResultsPerQuery": 10,
  "maxItems": 30,
  "market": "en-US",
  "safeSearch": "Moderate"
}
```

Use an Apify schedule to rerun this input daily or weekly. Join snapshots by `query` and `url`, then compare `position` and `retrievedAt` outside the Actor.

### Example output

A current local result for `bing search api` has this shape:

```json
{
  "query": "bing search api",
  "position": 1,
  "title": "Grounding with Bing | Microsoft Bing",
  "url": "https://www.microsoft.com/en-us/bing/apis",
  "domain": "microsoft.com",
  "snippet": "Enhance your large language models with real-time, web-based insights.",
  "page": 1,
  "market": "en-US",
  "safeSearch": "Moderate",
  "sourceUrl": "https://www.bing.com/search?q=bing+search+api&first=1&count=10&setmkt=en-US",
  "retrievedAt": "2026-09-11T06:14:21.321Z"
}
```

Bing can change text and ordering at any time, so this example demonstrates the schema rather than a promised current rank.

### How much does it cost to scrape Bing organic results?

This Actor uses pay-per-event pricing: one small run-start charge plus one `item` event for every accepted organic result saved to the dataset. Duplicate, invalid, empty, or failed records are not charged as result items.

The current BRONZE prices are **$0.0005 per run** and **$0.002304 per result**. For example:

Use the BRONZE formula **run start + result count × result price**. For example, a 10-result run is the $0.0005 start event plus 10 item events at $0.002304 each; a 100-result run uses the same start event plus 100 item events. Your plan tier determines the exact event price shown in Console. Platform usage behavior and prices are visible before starting a paid run.

### Reliability and retry behavior

The primary route requests Bing's server-rendered result HTML through an Apify datacenter proxy. A stable proxy identity is kept across pages for one query.

If Bing returns a verification page or an unrecognized HTML shape, the Actor tries Bing's public RSS representation for the same query. Network failures, proxy failures, HTTP 429, and temporary server failures are retried up to three times with exponential jitter and a fresh proxy identity.

The Actor fails visibly after retry exhaustion. It does not silently convert a challenge page into an empty successful dataset.

### Pagination and result limits

Bing controls the number and composition of results on each page. Later pages can repeat earlier destinations. The Actor deduplicates URLs per query, so a request for 20 results can legitimately return fewer than 20 unique rows.

`position` reflects the accepted unique organic ordering in the dataset for each query. `page` records the source page that produced a row.

### Recurring rank-tracking workflow

1. Create a task with a stable query list, market, and SafeSearch setting.
2. Add a daily or weekly schedule.
3. Export or integrate each run's dataset.
4. Match rows by `query` plus `url`.
5. Compare `position` across `retrievedAt` snapshots.
6. Alert in your own workflow when a tracked URL appears, disappears, or changes position.

Keeping the same inputs is important: changing market or SafeSearch can change the result set independently of organic ranking changes.

### Domain visibility audit

Search for a real brand and topic, such as:

```json
{
  "queries": ["Apify web scraping platform"],
  "maxResultsPerQuery": 10,
  "maxItems": 10,
  "market": "en-US",
  "safeSearch": "Moderate"
}
```

Filter the resulting dataset by `domain` to see which pages Bing surfaced. A missing domain means it was not present in the collected snapshot, not that it is absent from Bing's entire index.

### Export and integrations

The default dataset works with Apify's JSON, CSV, Excel, XML, RSS, and JSONL exports. Common patterns include:

- send every completed dataset to a webhook;
- append rows to Google Sheets through Make;
- load JSONL into a warehouse;
- compare scheduled-run datasets in Python;
- trigger a downstream Actor through an integration;
- let an agent retrieve current Bing evidence through MCP.

### Run through the Apify API with cURL

Replace `YOUR_TOKEN` with your Apify API token:

```bash
curl -X POST \
  "https://api.apify.com/v2/acts/automation-lab~bing-search-results-scraper/runs?token=YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "queries": ["bing search api"],
    "maxResultsPerQuery": 10,
    "maxItems": 10,
    "market": "en-US",
    "safeSearch": "Moderate"
  }'
```

Use the returned run ID to inspect status and retrieve the default dataset.

### Run with JavaScript

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

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('automation-lab/bing-search-results-scraper').call({
    queries: ['bing search api'],
    maxResultsPerQuery: 10,
    maxItems: 10,
    market: 'en-US',
    safeSearch: 'Moderate',
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

### Run with Python

```python
import os
from apify_client import ApifyClient

client = ApifyClient(os.environ["APIFY_TOKEN"])
run = client.actor("automation-lab/bing-search-results-scraper").call(run_input={
    "queries": ["bing search api"],
    "maxResultsPerQuery": 10,
    "maxItems": 10,
    "market": "en-US",
    "safeSearch": "Moderate",
})
items = client.dataset(run["defaultDatasetId"]).list_items().items
print(items)
```

### Use with MCP and AI agents

Add the Actor as an Apify MCP tool in Claude Code:

```bash
claude mcp add --transport http apify \
  "https://mcp.apify.com?tools=automation-lab/bing-search-results-scraper"
```

#### Claude Desktop, Cursor, and VS Code setup

Claude Desktop, Cursor, and VS Code can use this equivalent remote MCP configuration:

```json
{
  "mcpServers": {
    "apify": {
      "url": "https://mcp.apify.com?tools=automation-lab/bing-search-results-scraper"
    }
  }
}
```

Example prompts:

- "Search Bing US for `bing search api` and return the top 10 organic URLs."
- "Compare the domains ranking for `serp api` and `keyword research tool`."
- "Collect the first 20 Bing results for these keywords and group them by domain."

### Legality and responsible use

Bing result pages are public, but you are responsible for complying with applicable laws, platform terms, and the rights of destination sites. Do not use the Actor to collect sensitive personal data, evade access controls, or make automated decisions about individuals.

Result snippets can quote third-party pages. Respect copyright, attribution, retention, and downstream-use obligations.

### Limitations

- Organic web results only; no ads, maps, news, images, or answer panels.
- Rankings are snapshots and can differ by time, market, index, and source behavior.
- Market selection does not guarantee city-level geolocation.
- Bing can expose fewer unique rows than the requested maximum.
- The RSS fallback can contain fewer results than the HTML page.
- Snippets are nullable because some result cards omit them.
- The Actor does not store historical snapshots or calculate rank changes itself.

### Troubleshooting

#### The run returned fewer results than requested

The input is a maximum. Bing may expose a short page or duplicate URLs across pages. Inspect `page`, `sourceUrl`, and logs before increasing limits.

#### The run failed with a verification challenge

The Actor already retries with fresh proxy identities and uses the public RSS fallback. Retry later rather than launching many parallel runs, which can increase blocking.

#### Results differ from my browser

Confirm that `market` and `safeSearch` match your comparison. Browser location, cookies, experiment cohorts, and retrieval time can still affect ordering.

#### My input was rejected

Ensure `queries` is a non-empty array of unique strings, limits are integers within their documented ranges, and the market is one of the supported values.

### Related Automation Lab Actors

- [Bing Images Scraper](https://apify.com/automation-lab/bing-images-scraper) for image-search records rather than web results.
- [Bing Maps Places Scraper](https://apify.com/automation-lab/bing-maps-places-scraper) for local place and business data.
- [Google Organic Rank Tracker](https://apify.com/automation-lab/seo-rank-tracker) for Google-focused recurring organic position workflows.

### FAQ

#### Does this use the paid Bing Search API?

No. It extracts the public Bing result representation and does not require an Azure or Microsoft API key.

#### Can I search multiple keywords in one run?

Yes. Add up to 50 unique queries and use `maxItems` as the total cap.

#### Can I schedule rank tracking?

Yes. Save the input as an Apify task and attach a schedule. Compare the separate datasets downstream using `query`, `url`, `position`, and `retrievedAt`.

#### Is every requested rank guaranteed?

No. Bing decides how many unique organic results are available and can change ordering at any time.

#### Are failed or duplicate results charged?

No result-item event is emitted for failed, rejected, duplicate, or empty records. The one-time run-start event still applies after valid input starts execution.

# Actor input Schema

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

Keywords or phrases to search on Bing. Each result keeps its query and organic position for comparison across recurring runs.

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

Maximum organic results to collect for each query across Bing result pages.

## `maxItems` (type: `integer`):

Run-wide result cap across all queries. Use it to control dataset size and spend.

## `market` (type: `string`):

Language-country market used for result localization.

## `safeSearch` (type: `string`):

Bing SafeSearch level applied to every query.

## Actor input object example

```json
{
  "queries": [
    "bing search api"
  ],
  "maxResultsPerQuery": 20,
  "maxItems": 20,
  "market": "en-US",
  "safeSearch": "Moderate"
}
```

# Actor output Schema

## `overview` (type: `string`):

Open the ranked organic result records in the overview table.

# 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": [
        "bing search api"
    ],
    "maxResultsPerQuery": 20,
    "maxItems": 20,
    "market": "en-US",
    "safeSearch": "Moderate"
};

// Run the Actor and wait for it to finish
const run = await client.actor("automation-lab/bing-search-results-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": ["bing search api"],
    "maxResultsPerQuery": 20,
    "maxItems": 20,
    "market": "en-US",
    "safeSearch": "Moderate",
}

# Run the Actor and wait for it to finish
run = client.actor("automation-lab/bing-search-results-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": [
    "bing search api"
  ],
  "maxResultsPerQuery": 20,
  "maxItems": 20,
  "market": "en-US",
  "safeSearch": "Moderate"
}' |
apify call automation-lab/bing-search-results-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,automation-lab/bing-search-results-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/HLgyFbiEF9OdkRCIc/builds/8cE9MRjBWCgvB6PPe/openapi.json
