# Bing Search and Keyword Scraper (`karamelo/bing-search-and-keyword-scraper`) Actor

Collect structured Bing search results and related keyword suggestions for newline-separated queries or Bing search URLs.

- **URL**: https://apify.com/karamelo/bing-search-and-keyword-scraper.md
- **Developed by:** [karamelo](https://apify.com/karamelo) (community)
- **Stats:** 2 total users, 1 monthly users, 75.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $4.00 / 1,000 result pages

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?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

### Bing search results and keyword ideas in one dataset

Bing Search and Keyword Scraper turns a list of search phrases or Bing search URLs into structured records that are easy to review, export, compare, and reuse in an automated workflow. Each record represents one requested result page and includes the search phrase, page number, market and language settings, the total result count when shown, organic results, paid results, People Also Ask questions, and related query suggestions.

The Actor is useful when a search engine results page is the starting point for a decision. SEO teams can compare ranking positions across recurring runs. Content teams can use related queries and questions to expand a brief. Sales and research teams can collect destination URLs and descriptions for a defined set of topics. Analysts can export the dataset to JSON, CSV, Excel, or another format supported by the Apify platform.

You can enter several queries at once by putting one phrase on each line. You can also paste full Bing search URLs when the URL already represents the search you want to repeat. A conservative first run is one query and one page; increase the page limit only after confirming that the returned fields match your use case.

### Why use this Actor?

- **One record per requested page** — page number, search URL, market, and language remain alongside the extracted groups, making multi-page runs easier to audit.
- **Multiple SERP groups** — organic results, paid results, People Also Ask entries, and related queries are kept in separate fields instead of being mixed into one list.
- **Search phrase or Bing URL input** — use a readable keyword list for batch research or reuse a Bing search URL that already contains the desired phrase.
- **Localization controls** — set a market such as `en-US` and an optional language such as `en` when regional search context matters.
- **Bounded pagination** — each query accepts a declared page limit from 1 through 20, which keeps a run finite and makes cost planning easier.
- **Export-ready data** — the dataset uses predictable field names, arrays for repeated results, and nullable values where Bing does not show a field.

### Who is Bing Search and Keyword Scraper for?

#### SEO and content research

Run a small set of target phrases and retain the `position`, `title`, `url`, `domain`, and `description` values from `organicResults`. On a later run, compare the same query and page to identify changes in visible results. Use `relatedQueries` and `peopleAlsoAsk` to expand a content outline without manually copying suggestions from every page.

#### Competitive and market intelligence

Create a query list that reflects product categories, brands, or customer problems. The result arrays provide a repeatable starting point for reviewing which domains appear, which messages are visible, and whether advertising results are present. Keep each query in a separate line so the output can be grouped by topic after export.

#### Reporting and workflow automation

The flat top-level record is suitable for a scheduled dataset. A downstream workflow can select `organicResults`, flatten one result per row, store `relatedQueries` as a keyword list, or send a summary when a target domain appears at a changed position. The Actor does not make a business decision for you; it supplies a consistent search snapshot for the next step.

### Getting started

#### 1. Run one query and one page

Use this smallest useful input:

```json
{
  "queries": "apify",
  "maxPagesPerQuery": 1
}
```

Open the Actor, paste the input into the JSON editor, run it, and inspect the default dataset. Starting with one page helps you confirm the market, language, result groups, and URL format before expanding the run.

#### 2. Search several phrases in one run

Put each phrase on its own line:

```json
{
  "queries": "bing search scraper\nBing keyword research\nSERP monitoring",
  "maxPagesPerQuery": 1,
  "marketCode": "en-US",
  "languageCode": "en"
}
```

The Actor creates one page record for each query. If a query produces no paid results or no related suggestions, the corresponding array is empty; this is a valid result rather than a missing record.

#### 3. Repeat a search represented by a Bing URL

Full Bing search URLs are accepted when they contain a `q` parameter:

```json
{
  "queries": "https://www.bing.com/search?q=content+gap+analysis",
  "maxPagesPerQuery": 2,
  "marketCode": "gb",
  "languageCode": "en"
}
```

The search phrase is taken from the URL, while the market and language values in the input control the run. URLs from other domains are not accepted as search inputs.

### Input reference

| Parameter | Type | Default | Required | Description |
|---|---|---:|:---:|---|
| `queries` | string | — | Yes | One search phrase or full Bing search URL per line. Blank lines are ignored. Up to 50 non-empty lines are accepted. |
| `maxPagesPerQuery` | integer | `1` | No | Number of result pages per query. The allowed range is `1`–`20`; each page represents up to 10 result positions. |
| `marketCode` | string | `""` | No | Select a Bing market such as `en-US`, or use a supported two-letter country code such as `us`. An empty value leaves the market unspecified. |
| `languageCode` | string | `""` | No | Select a supported language such as `en`, `en-gb`, or `zh-hans`. An empty value leaves the language unspecified. |

`queries` is a string rather than an array so that a batch can be pasted directly into the Console editor. A full URL must point to `bing.com` and include a search phrase in `q`. For a large batch, split work into several runs so each dataset remains easy to inspect and downstream jobs can rerun a smaller unit.

The market selector includes Argentina, Australia, Austria, Belgium, Brazil, Canada, Chile, Denmark, Finland, France, Germany, Hong Kong, India, Indonesia, Italy, Japan, Korea, Malaysia, Mexico, the Netherlands, New Zealand, Norway, mainland China, Poland, the Philippines, Russia, South Africa, Spain, Sweden, Switzerland, Taiwan, Türkiye, the United Kingdom, and the United States. Where Bing provides more than one market variant, the selector distinguishes the language or regional variant, for example `fr-CA`, `de-CH`, and `es-US`. Two-letter aliases map to the default market for that country.

The language selector supports Arabic, Basque, Bengali, Bulgarian, Catalan, simplified and traditional Chinese, Croatian, Czech, Danish, Dutch, English, Estonian, Finnish, French, Galician, German, Gujarati, Hebrew, Hindi, Hungarian, Icelandic, Italian, Japanese, Kannada, Korean, Latvian, Lithuanian, Malay, Malayalam, Marathi, Norwegian, Polish, Portuguese, Punjabi, Romanian, Russian, Serbian, Slovak, Slovenian, Spanish, Swedish, Tamil, Telugu, Thai, Turkish, Ukrainian, and Vietnamese. Use the exact lowercase value shown by the Console selector.

Market and language affect the context in which Bing presents results. They do not guarantee that every result will come from a particular country or that every page will contain every optional SERP section. Bing may show different result groups for different phrases, markets, languages, devices, and times.

### Output reference

One dataset row represents one query-page combination. A run with three queries and two pages per query can therefore produce up to six page records, subject to source availability.

| Field | Type | Description |
|---|---|---|
| `query` | string | Search phrase represented by the record. |
| `page` | integer | One-based result page number. |
| `searchUrl` | string | Bing search URL represented by the record. |
| `marketCode` | string | Market used for the search, or an empty string when none was supplied. |
| `languageCode` | string | Language used for the search, or an empty string when none was supplied. |
| `resultsTotal` | integer or `null` | Total count shown by Bing when available. |
| `organicResults` | array | Non-advertising results. Each item includes position, title, URL, displayed URL, domain, description, date, and result type. |
| `paidResults` | array | Advertising results with the same item shape as organic results. |
| `peopleAlsoAsk` | array | Suggested questions with an answer and source URL when available. |
| `relatedQueries` | array of strings | Related keyword or query suggestions shown for the search. |
| `scrapedAt` | string | ISO 8601 timestamp for the collected record. |

Here is a shortened, illustrative record. Large arrays are abbreviated for readability; the stored record keeps the complete values available on the page.

```json
{
  "query": "apify",
  "page": 1,
  "searchUrl": "https://www.bing.com/search?q=apify&count=10&mkt=en-US&setLang=en",
  "marketCode": "en-US",
  "languageCode": "en",
  "resultsTotal": 49400,
  "organicResults": [
    {
      "position": 1,
      "title": "Example result title",
      "url": "https://example.com/page",
      "displayedUrl": "example.com/page",
      "domain": "example.com",
      "description": "Example result description.",
      "date": null,
      "type": "organic"
    }
  ],
  "paidResults": [],
  "peopleAlsoAsk": [
    {
      "question": "What is an example search question?",
      "answer": "Example answer text.",
      "url": "https://example.com/answer"
    }
  ],
  "relatedQueries": ["example related query"],
  "scrapedAt": "2026-09-16T16:51:40.975Z"
}
```

`resultsTotal` is reported by Bing and can be `null` when the page does not show a count. Optional text fields such as `description`, `date`, `displayedUrl`, and People Also Ask answers can also be `null`. Empty arrays mean that the corresponding group was not present or did not contain usable entries. `scrapedAt` is UTC, expressed as an ISO 8601 timestamp.

### Tips for better results

Start with one page for each query. Search result pages can change over time, so a small run gives you a baseline and makes it easier to decide whether more pages add useful coverage. Use `maxPagesPerQuery` when you need positions beyond the first page, but remember that later pages may contain fewer results or repeated content when the source changes its presentation.

Use a focused query list. Ten specific phrases are usually easier to analyze than one very broad batch of fifty phrases. If you need several markets, keep market-specific inputs in separate runs so the output remains clear about which context produced each record.

Use `domain` as a grouping aid, but keep the full `url` for follow-up review. Domains can repeat across many results, and a displayed URL is presentation text rather than a substitute for the destination URL. Treat `resultsTotal` as source-reported context, not as a precise estimate of all pages you can collect.

For recurring monitoring, keep the query text, page limit, market, and language stable. Store the run time and compare result positions or URLs between dataset exports. A change may reflect new content, advertising, localization, source ranking changes, or a temporary difference in the page—not necessarily a permanent ranking move.

### Practical workflows

#### Build a keyword expansion list

Start with ten seed phrases in `queries` and use one page per phrase. Export `relatedQueries` and `peopleAlsoAsk` into a planning table. Remove duplicates, group phrases by intent, and send the resulting shortlist to your editorial or research process. Check the source page before treating a suggestion as a final keyword because suggestions can be broad, seasonal, or influenced by the selected market and language.

#### Monitor a set of search positions

Create a stable input file with one phrase per line, one or two pages per phrase, and an explicit market. Schedule the Actor through Apify, then compare `organicResults` between runs by `query`, `page`, and result URL. Flag new URLs, missing URLs, and position changes for human review. Keep a small first run and expand only if the additional pages produce decisions worth the extra run resources.

#### Review advertising and organic visibility together

Use a focused commercial query list and inspect `paidResults` beside `organicResults`. Compare titles, descriptions, domains, and destination URLs to understand the visible message mix for each phrase. An empty `paidResults` array means no usable advertising result was present in that record; it does not prove that the phrase has no advertising market at another time or location.

### API and automation

The Actor can be started through the public Apify API using its manifest identity, `karamelo/bing-search-and-keyword-scraper`. The following example starts a small run; replace the token placeholder with an Apify API token and keep it outside source files and shared documents.

```bash
curl -X POST "https://api.apify.com/v2/acts/karamelo~bing-search-and-keyword-scraper/runs?token=YOUR_APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "queries": "apify\ncrawlee",
    "maxPagesPerQuery": 1,
    "marketCode": "en-US",
    "languageCode": "en"
  }'
```

The start response contains the run identifier and the default dataset identifier. Wait for the run to finish before treating the dataset as final. Then retrieve the items with the dataset API:

```bash
curl "https://api.apify.com/v2/datasets/DATASET_ID/items?clean=true&format=json&token=YOUR_APIFY_TOKEN"
```

You can use the same lifecycle in a scheduled job: trigger a run with a saved input, wait for a terminal run status, read the default dataset, and pass the records to reporting or analysis. Apify schedules and webhooks can handle the timing and notification layer. Keep the input conservative until you understand how many page records your batch creates.

### Pricing and run planning

This release does not state a fixed per-result price in the public Actor contract. Plan for the Apify run's resource usage and any account-level charges for compute, storage, or other platform services that apply to your plan. The most reliable estimate is a one-query, one-page trial using the same market and language that the production workflow will use.

| Starting scope | Planning purpose |
|---|---|
| 1 query × 1 page | Confirm fields, localization, and source coverage. |
| 5 queries × 1 page | Estimate the size of a focused keyword batch. |
| 10 queries × 2 pages | Evaluate whether second-page coverage changes the decision. |

The number of dataset rows is bounded by query count multiplied by `maxPagesPerQuery`, with a maximum of 50 queries and 20 pages per query in one run. Result arrays can vary in size, and a page may contain no paid results or no related queries.

### Limitations and good-to-know details

- Bing controls the visible page content, result ordering, total count, advertising presence, and suggestion groups. These can change between runs.
- The Actor accepts up to 50 non-empty queries and 20 pages per query. This is an Actor limit, not a promise that Bing will supply every possible result.
- Search results are best-effort snapshots. Do not treat an empty optional array as proof that the underlying topic has no questions, ads, or related searches.
- Result descriptions and dates are source-provided presentation values and may be absent, shortened, or formatted differently across markets.
- A Bing URL must contain a `q` parameter. Other URL settings are not a substitute for the Actor's explicit market and language inputs.
- Public search content can include links to pages that later become unavailable, move, require access, or change their text.
- The Actor is intended for public Bing search pages. It does not promise access to private accounts, private content, or restricted material.

### Troubleshooting

| Symptom | Likely cause | What to inspect or change |
|---|---|---|
| The run is rejected before collecting data | `queries` is missing, empty, too large, or a URL is not a Bing search URL with `q` | Start with one plain phrase such as `apify`, then add lines one at a time. |
| `organicResults` is empty | The page did not expose usable result entries for that query or market | Try a more specific phrase, check the market and language, and run the query again later. |
| `paidResults` or `relatedQueries` is empty | Bing did not show that optional group for the selected search context | Treat the empty array as valid output; compare another phrase or market if the group matters. |
| The total count is `null` | Bing did not display a usable count on the page | Use the result arrays and record timestamp for analysis instead of filling the value manually. |
| A URL or description looks different from an earlier run | Search presentation and ranking changed | Compare the complete record, market, language, page, and `scrapedAt` before drawing a conclusion. |
| A larger run costs more than expected | More query-page combinations create more dataset rows and resource use | Test one page first, then increase `maxPagesPerQuery` only where the extra coverage is useful. |

### Frequently asked questions

#### Can I enter several Bing keywords at once?

Yes. Put one phrase per line in `queries`. Empty lines are ignored, and up to 50 non-empty lines are accepted in one run.

#### Can I reuse a Bing search URL?

Yes. The URL must point to `bing.com` and include a `q` search phrase. The Actor uses the phrase from the URL and applies the input's market and language values.

#### How many pages can I collect?

Set `maxPagesPerQuery` from 1 through 20. The number of rows is bounded by the number of queries multiplied by that page limit, while the number of results inside each row depends on what Bing displays.

#### Are keyword suggestions separate from search results?

Yes. Related suggestions are returned in `relatedQueries`, and question-style suggestions are returned in `peopleAlsoAsk`. Organic and paid results remain in their own arrays.

#### Why are some fields `null`?

Fields are nullable when Bing does not show that value for a particular result or page. Keeping `null` makes the distinction between unavailable data and an empty string explicit.

#### Can I schedule recurring runs?

Yes. Use an Apify schedule with a saved JSON input, then compare the resulting datasets by query, page, URL, and collection time. Start with a small interval and review source changes before increasing scope.

#### Is this suitable for personal-data collection?

Use it only for a legitimate, documented purpose. Search pages can link to personal or sensitive information even when the search page itself is public. Review applicable privacy, intellectual-property, marketing, and contractual requirements before collecting, storing, or contacting anyone based on the results.

### Responsible use

You are responsible for choosing lawful queries, respecting applicable Bing and Apify terms, and handling exported data appropriately. Public availability does not automatically make every downstream use appropriate. Avoid collecting sensitive personal information unless you have a clear legal basis and a documented need, and apply retention and access controls to any dataset that could identify people or organizations.

Use the Actor for research, monitoring, content planning, and other legitimate workflows. Validate important findings against the current source page and keep a human review step for decisions involving reputation, eligibility, outreach, or compliance. A small, well-defined run is the best way to confirm that the result fields and source context fit your use case.

### Next step

Run one query with `maxPagesPerQuery: 1`, inspect the dataset, and confirm that the result groups and localization match your objective. Once the baseline is useful, add focused query lines or a second page and connect the dataset to your reporting or analysis workflow.

# Actor input Schema

## `queries` (type: `string`):

Enter one or more keywords or full search URLs.

## `maxPagesPerQuery` (type: `integer`):

Maximum number of pages to retrieve for each query.

## `marketCode` (type: `string`):

Select the market for your search results. You can also use a lowercase country code such as us, which is mapped to the appropriate market code.

## `languageCode` (type: `string`):

Select language for search results. If left blank, it defaults to the language associated with the selected market.

## Actor input object example

```json
{
  "queries": "apify\nhttps://www.bing.com/search?q=crawlee",
  "maxPagesPerQuery": 1,
  "marketCode": "",
  "languageCode": ""
}
```

# Actor output Schema

## `results` (type: `string`):

No description

# 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
https://www.bing.com/search?q=crawlee`
};

// Run the Actor and wait for it to finish
const run = await client.actor("karamelo/bing-search-and-keyword-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
https://www.bing.com/search?q=crawlee""" }

# Run the Actor and wait for it to finish
run = client.actor("karamelo/bing-search-and-keyword-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\\nhttps://www.bing.com/search?q=crawlee"
}' |
apify call karamelo/bing-search-and-keyword-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,karamelo/bing-search-and-keyword-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/rLvrMhetVZ8iLtF2W/builds/5g7kYCisyNsgwxedx/openapi.json
