# Marketplace Price Tracker & Comparison (`akatra/marketplace-price-intelligence`) Actor

Compare prices, sellers, stock and changes across marketplaces.

- **URL**: https://apify.com/akatra/marketplace-price-intelligence.md
- **Developed by:** [Akatra](https://apify.com/akatra) (community)
- **Categories:** E-commerce
- **Stats:** 1 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$2.00 / 1,000 offer results

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

## Marketplace Price Tracker & Comparison

by Akatra

**Compare prices, sellers, stock and changes across marketplaces.**

Trendyol Hepsiburada Price Tracker & Comparison: one normalized API to compare marketplace prices, sellers, stock and changes. Search once, compare across marketplaces, track what changed.

Turkey-first, global-ready marketplace intelligence. Version 1 covers Turkish marketplaces and two Turkish price-comparison sites. The data model, marketplace ids and matching engine already carry region, country and currency, so more regions can be added without changing the output.

### What does Marketplace Price Tracker & Comparison do?

It does five things in one run and returns one table:

1. **Discover.** Searches each selected marketplace for your query, or opens the product URLs you give.
2. **Normalize.** Maps every offer to the same fields: price as a number, currency, seller, stock, rating, product ids.
3. **Match.** Groups identical products across marketplaces. Barcode (GTIN) matches are `exact`. Title-only matches are `probable` and are never used for a price verdict.
4. **Compare.** For safely matched groups it adds lowest price, highest price, price difference, cheapest marketplace and `isCheapest` to every row.
5. **Detect changes.** With a monitor key, later runs report price, stock and seller changes and can return only what changed.

One marketplace failing never fails the run. Each source reports its own health in the run summary.

### Supported sources

Status comes from live tests on the Apify platform, not from the existence of an adapter.

| Id | Source | Type | Status | Search | Product page | Sellers | Notes |
| --- | --- | --- | --- | --- | --- | --- | --- |
| `trendyol_tr` | Trendyol | marketplace | SUPPORTED | yes | yes | every seller of a product, seller score | Barcode on product pages |
| `hepsiburada_tr` | Hepsiburada | marketplace | SUPPORTED | yes | yes | featured seller plus other sellers shown on the page | Barcode on product pages |
| `n11_tr` | n11 | marketplace | SUPPORTED | yes | yes | featured seller plus other sellers, stock count | Barcode on product pages |
| `pazarama_tr` | Pazarama | marketplace | SUPPORTED | yes | yes | featured seller name | No barcode field. Occasionally refuses a request; the run reports it |
| `ciceksepeti_tr` | Çiçeksepeti | marketplace | SUPPORTED | yes | yes | seller name, id and score | No barcode field |
| `pttavm_tr` | PttAVM | marketplace | SUPPORTED | yes | yes | seller name | No barcode or brand field |
| `amazon_tr` | Amazon Türkiye | marketplace | BETA | yes | yes | featured seller only | Not in the default selection. amazon.com.tr sometimes answers with a bot check; such requests are reported as blocked. Product pages are read only for product URLs you give and when "Include every seller" is on, at most 20 per run |
| `akakce_tr` | Akakçe | comparison_source | SUPPORTED | yes | yes | shop and seller of every listed offer | Not a marketplace: a price-comparison site |
| `cimri_tr` | Cimri | comparison_source | SUPPORTED | yes | yes | shop and seller of every listed offer | Not a marketplace: a price-comparison site |

Akakçe and Cimri rows are labelled `sourceType = comparison_source`. They show what the comparison site lists at the time of the run. They are linked to the matching marketplace listing where possible, and they never decide the cheapest marketplace.

No adapter is DISABLED in this version.

### What people use it for

- **Price monitoring.** Track your own products and competitors on several marketplaces with one schedule.
- **Repricing input.** Feed the lowest price, the gap to the lowest price and the cheapest seller into your pricing rules.
- **Market research.** See which marketplaces carry a product, at what price and from which sellers.
- **Stock and buy box watching.** Get a row when a product goes out of stock or the featured seller changes.
- **AI agents.** Answer "where is this cheapest", "what changed since yesterday" and "which rows could not be matched" from machine-readable fields.

### What data can you extract?

One row per offer. Fields that a source does not provide are `null`. Nothing is guessed.

| Group | Fields |
| --- | --- |
| Source | `region`, `countryCode`, `marketplace`, `marketplaceName`, `sourceType`, `offerOrigin`, `sourceUrl`, `scrapedAt` |
| Product | `marketplaceProductId`, `productUrl`, `title`, `brand`, `model`, `sku`, `gtin`, `mpn`, `variant`, `condition`, `category`, `imageUrl` |
| Price | `currentPrice`, `originalPrice`, `basketPrice`, `discountPercent`, `currency` |
| Seller | `sellerName`, `sellerId`, `sellerUrl`, `sellerRating`, `sellerRatingScale`, `isFeaturedOffer` |
| Comparison-site shop | `merchantName`, `merchantMarketplace`, `merchantProductId`, `sourceOfferCount` |
| Availability | `stockStatus`, `availabilityEvidence`, `stockQuantity`, `shippingPrice`, `freeShipping`, `deliveryText` |
| Ratings (aggregate only) | `rating`, `reviewCount` |
| Matching | `productGroupId`, `matchLevel`, `matchReason` |
| Comparison | `comparisonEligible`, `groupOfferCount`, `groupMarketplaceCount`, `groupAvailableMarketplaceCount`, `lowestPrice`, `highestPrice`, `priceDifference`, `priceDifferencePercent`, `cheapestMarketplace`, `cheapestMarketplaces`, `cheapestSeller`, `highestMarketplace`, `isCheapest`, `priceGapToLowest` |
| Changes | `monitorStatus`, `changeTypes`, `previousPrice`, `priceChange`, `priceChangePercent`, `previousOriginalPrice`, `previousStockStatus`, `previousSeller`, `firstSeenAt`, `lastSeenAt`, `changedAt` |
| Search | `searchQuery`, `rank` |

`availabilityEvidence` tells you how strong the stock information is: `explicit` when the source states it, `indirect` when the product is only listed with a buyable price, `none` when there is no evidence.

Prices are numbers in the row's `currency`. Turkish formats such as `64.999,90 TL` are parsed with exact decimal arithmetic.

### How to use it

1. Open the Actor and type one or more product names in **Search queries**, for example `iPhone 16 128 GB`. Be specific: every word of the query must appear in a listing.
2. Pick the **Marketplaces**, or leave the default selection.
3. Optional: paste product URLs in **Product or search URLs** to track specific products.
4. Optional: set a **Monitor key** and turn on **Return only what changed** to get changes on later runs.
5. Start the run. Download the dataset as JSON, CSV or Excel, or read it through the API.

### Input example (JSON)

Search and compare:

```json
{
  "region": "TR",
  "searchQueries": ["iPhone 16 128 GB"],
  "marketplaces": ["trendyol_tr", "hepsiburada_tr", "n11_tr", "pazarama_tr"],
  "maxResultsPerMarketplace": 10,
  "includeSellers": true
}
```

Track specific product pages and return only changes above 3 percent:

```json
{
  "startUrls": [
    { "url": "https://www.trendyol.com/apple/iphone-16-128gb-beyaz-p-857296082" },
    { "url": "https://www.hepsiburada.com/apple-iphone-16-128gb-beyaz-p-HBCV00006Y4HFL" },
    { "url": "https://www.n11.com/urun/apple-iphone-16-128-gb-apple-turkiye-garantili-59257801" }
  ],
  "monitorKey": "iphone-16-white",
  "onlyChanged": true,
  "priceChangeThresholdPercent": 3
}
```

Add the comparison sites and the beta Amazon adapter:

```json
{
  "searchQueries": ["dyson v15"],
  "marketplaces": ["trendyol_tr", "hepsiburada_tr", "amazon_tr", "akakce_tr", "cimri_tr"],
  "maxResultsPerMarketplace": 5
}
```

Marketplace ids always carry the region (`trendyol_tr`, `amazon_tr`). Short names such as `trendyol` are accepted as input and are returned as the full id.

### Sample output (JSON)

A real row from a run on 3 October 2026: one of three Hepsiburada sellers of a product that was matched by barcode on four marketplaces.

```json
{
  "region": "TR",
  "countryCode": "TR",
  "marketplace": "hepsiburada_tr",
  "marketplaceName": "Hepsiburada",
  "sourceType": "marketplace",
  "offerOrigin": "product_page",
  "marketplaceProductId": "HBCV00006Y4HFL",
  "productUrl": "https://www.hepsiburada.com/apple-iphone-16-128gb-beyaz-p-HBCV00006Y4HFL",
  "title": "iPhone 16 128GB Beyaz",
  "brand": "Apple",
  "model": null,
  "sku": "HBCV00006Y4HFL",
  "gtin": "0195949822124",
  "mpn": null,
  "variant": "Beyaz",
  "condition": "new",
  "currentPrice": 74979.08,
  "originalPrice": null,
  "basketPrice": null,
  "discountPercent": null,
  "currency": "TRY",
  "sellerName": "Troy Apple",
  "sellerId": "1da370aa-3e19-4ddc-8520-f5b1cf9e1066",
  "sellerUrl": null,
  "sellerRating": 9.7,
  "sellerRatingScale": 10,
  "isFeaturedOffer": false,
  "merchantName": null,
  "merchantMarketplace": null,
  "merchantProductId": null,
  "sourceOfferCount": null,
  "stockStatus": "in_stock",
  "availabilityEvidence": "explicit",
  "stockQuantity": null,
  "shippingPrice": null,
  "freeShipping": false,
  "deliveryText": null,
  "rating": 4.8,
  "reviewCount": 3613,
  "imageUrl": "https://productimages.hepsiburada.net/s/777/375/110000767394638.jpg/format:webp",
  "category": "Telefon > Cep Telefonu > iPhone iOS Telefonlar",
  "searchQuery": null,
  "rank": null,
  "productGroupId": "TR:gtin:0195949822124",
  "matchLevel": "exact",
  "matchReason": "same_gtin",
  "comparisonEligible": true,
  "groupOfferCount": 17,
  "groupMarketplaceCount": 4,
  "groupAvailableMarketplaceCount": 4,
  "lowestPrice": 73399,
  "highestPrice": 99999,
  "priceDifference": 26600,
  "priceDifferencePercent": 36.24,
  "cheapestMarketplace": null,
  "cheapestMarketplaces": ["n11_tr", "pazarama_tr", "trendyol_tr"],
  "cheapestSeller": "MediaMarkt",
  "highestMarketplace": "trendyol_tr",
  "isCheapest": false,
  "priceGapToLowest": 1580.08,
  "monitorStatus": "baseline",
  "changeTypes": [],
  "previousPrice": null,
  "priceChange": null,
  "priceChangePercent": null,
  "previousOriginalPrice": null,
  "previousStockStatus": null,
  "previousSeller": null,
  "firstSeenAt": "2026-10-03T19:08:05Z",
  "lastSeenAt": "2026-10-03T19:08:05Z",
  "changedAt": null,
  "sourceUrl": "https://www.hepsiburada.com/apple-iphone-16-128gb-beyaz-p-HBCV00006Y4HFL",
  "scrapedAt": "2026-10-03T19:08:08Z"
}
```

Three marketplaces tied at the lowest price in that run, so `cheapestMarketplace` is `null` and `cheapestMarketplaces` lists the three. The same store, MediaMarkt, held that price on each of them.

A changed row from the next run with the same monitor key, about two minutes later (only the change fields are shown). It is a shop offer listed by the comparison site Cimri:

```json
{
  "marketplace": "cimri_tr",
  "sourceType": "comparison_source",
  "merchantName": "Vatan Bilgisayar",
  "title": "Apple iPhone 16 128 GB Beyaz",
  "currentPrice": 73399,
  "currency": "TRY",
  "monitorStatus": "changed",
  "changeTypes": ["PRICE_CHANGED"],
  "previousPrice": 82999,
  "priceChange": -9600,
  "priceChangePercent": -11.57,
  "firstSeenAt": "2026-10-03T19:08:05Z",
  "lastSeenAt": "2026-10-03T19:10:02Z",
  "changedAt": "2026-10-03T19:10:02Z"
}
```

### How products are matched

Comparing prices is only useful when the products are really the same, so every row says how it was matched.

| `matchLevel` | Meaning | Used for the price verdict? |
| --- | --- | --- |
| `exact` | Same barcode (GTIN), or the same marketplace listing reached through another source | yes |
| `strong` | Same brand and manufacturer part number, or a listing id that equals a barcode another offer declares | yes |
| `probable` | No shared identifier. Brand, model words, storage, memory, colour, pack size, sizes and condition read from the titles are identical, and they point to exactly one product group | no |
| `unmatched` | Anything else. `matchReason` says why | no |

Rules that keep groups honest:

- 128 GB and 256 GB, different colours, a single item and a multipack, new and refurbished, different refurbished grades and different model generations are never the same group.
- Accessories ("uyumlu kılıf", chargers, filters) and gift bundles are never matched to the device.
- A title that fits two different product groups stays `unmatched` with `matchReason = ambiguous_multiple_candidate_groups`.
- A shared barcode or part number is not enough when the titles contradict it (a refurbished or graded listing, another size or colour, a multipack or a gift bundle that reuses the barcode): the contradicting offer leaves the group with `matchReason = identifier_shared_with_conflicting_attributes`.
- Price is never used as evidence that two offers are the same product.
- `probable` rows and comparison-site rows join a group for reference only: `comparisonEligible` is `false` and `isCheapest` is `null`.
- `cheapestMarketplace` is filled only when the product can be bought on at least two marketplaces (definitive match, priced, not out of stock) and one of them is strictly cheapest. On a tie it is `null` and `cheapestMarketplaces` lists the tied ones. When only one marketplace has it available, nothing is named cheapest (`cheapestMarketplace`, `cheapestSeller` and `isCheapest` are `null`); `groupAvailableMarketplaceCount` is 1.
- Offers are compared only inside one region and one currency. There is no currency conversion in this version.

Colour is part of the identity: the white and the black version of a phone are two groups, because their prices and stock differ.

### Change tracking

Set `monitorKey` to name a tracking job and run the Actor on a schedule.

- **First run for a key:** every offer is stored as the baseline and returned with `monitorStatus = baseline`. Nothing is reported as a change.
- **Later runs:** each offer is `unchanged`, `changed` or `new`. With `onlyChanged = true` only `changed`, `new` and `removed` rows are written.
- **Not checked:** when the product page behind a search result cannot be read in a run (blocked, timed out, or it shows another variant), the row carries the search-result data and `monitorStatus = not_checked`. It is not compared and the history is left as it was, so a temporary failure is never reported as a new offer or a price change. With `onlyChanged = true` such rows are not written.
- **Change types:** `PRICE_CHANGED`, `ORIGINAL_PRICE_CHANGED`, `STOCK_CHANGED`, `SELLER_CHANGED`, `NEW_OFFER`, `PRODUCT_REMOVED`, `PRODUCT_RETURNED`.
- **Threshold:** `priceChangeThresholdPercent = 3` ignores price moves under 3 percent. The change is measured against the last reported price, so several small moves add up. Stock and seller changes are never hidden by the threshold.
- **Removal is conservative.** `PRODUCT_REMOVED` is reported only for product URLs you track (it is tracked per URL), and only after two runs in a row received an explicit "product not found" answer. A timeout, a block or a missing search result is never a removal. The summary counts such cases as temporarily unreachable.
- **If the history store is unreachable** the run still returns every offer, with `monitorStatus = off` and a warning in the summary.
- **Keys are isolated.** Different monitor keys never share history, and history is stored per region and marketplace in your own account (named key-value store `marketplace-price-monitor`). Offers not seen for 180 days are dropped from the history.
- With `onlyChanged = true` and no key, a key is derived from the queries, URLs and marketplaces. Changing any of them starts a new baseline.

Good to know: marketplaces rotate the featured seller of popular products among sellers with the same price. Those rotations appear as `SELLER_CHANGED` on the featured row; the seller that lost the position keeps its history and is not reported as new. A product that enters the top results of a search for the first time appears as `NEW_OFFER`.

### Use it with AI agents, MCP and the API

Every question an agent is likely to ask maps to a field:

| Question | Field |
| --- | --- |
| Where is this product cheapest? | `cheapestMarketplace`, `cheapestMarketplaces`, `isCheapest` |
| Which seller has the lowest price? | `cheapestSeller`, or the row with `isCheapest = true` |
| How big is the difference? | `priceDifference`, `priceDifferencePercent`, `priceGapToLowest` |
| Which marketplaces have it in stock? | `stockStatus` with `availabilityEvidence` |
| What changed since the last run? | `monitorStatus`, `changeTypes`, `previousPrice`, `previousStockStatus`, `previousSeller` |
| Which results could not be matched with confidence? | `matchLevel` of `probable` or `unmatched`, with `matchReason` |
| Which source failed in this run? | `adapters[].health` in the `SUMMARY` record |

The run writes a `SUMMARY` record to the default key-value store with queries and URLs processed, offers found and written, matched and unmatched counts, change counts, requests, cache hits, bytes processed, warnings and one entry per source with its health: `success`, `partial`, `no_results`, `blocked`, `rate_limited`, `parse_error`, `temporarily_unavailable` or `unsupported`. The health describes this run only.

Call the Actor through the Apify API, the Apify MCP server, or any Apify integration. Dataset views `overview`, `comparison` and `changes` give ready-made column sets.

### Pricing: pay per result

You pay per offer row written to the dataset. See the Pricing tab for the current price. Rows that `onlyChanged` suppresses are not written and are not charged. Sources that fail in a run produce no rows and cost nothing. You can cap the cost of a run with the maximum charge setting; the run stops writing at the cap, and tracked changes that were not written are reported again by the next run.

### Run status and messages

A run ends as failed only when the input is invalid. Everything else ends as succeeded with a message that says what happened.

| Message | Meaning |
| --- | --- |
| `Saved N offer(s) from X/Y source(s)` | Normal result. X of Y sources returned data |
| `... product group(s) compared` | Number of groups with a price comparison |
| `monitor baseline created` | First run of this monitor key |
| `... unchanged offer(s) not repeated` | Rows suppressed by `onlyChanged` |
| `unavailable this run: ...` | Sources that were blocked, rate limited or returned an unexpected page. Details are in `SUMMARY` |
| `Nothing matched every word of the query` | Try a shorter or more general query |
| `Stopped early: the run's maximum charge was reached` | The saved rows are complete; raise the cap to get the rest |
| `Invalid input: ...` | The only failed status. The message names the field |

### Good to know

- Data is fetched at run time. It is a snapshot of what each site showed during the run, not a live feed.
- Search results are filtered: a listing is kept only when every word of your query appears in it. Marketplaces pad results with loosely related items, and those are dropped instead of being returned.
- The numeric id in many Pazarama URLs equals the product barcode, but Pazarama does not label it as one, so `gtin` stays `null` for Pazarama rows. The id is used for matching only when it equals a barcode that another offer declares.
- On Pazarama, Çiçeksepeti and PttAVM the price shown as "Sepette" or "Sepete Özel" (in basket) is the price a buyer pays, so it is the `currentPrice`; the listed price is the `originalPrice` and `basketPrice` repeats the basket price. `basketPrice` is not filled for the other sources.
- On Hepsiburada a discounted product carries two prices; `currentPrice` is the discounted one the page shows and `originalPrice` the list price.
- One n11 product URL covers several colours, storage sizes and sellers. The Actor keeps the seller and variant parameters of the URL, and the `marketplaceProductId` of an n11 row names the variant (for example `59257801:dahili-hafiza=128-gb,renk=beyaz`). A bare n11 URL shows whichever seller and variant n11 features at that moment; add the variant parameters to track one variant.
- Trendyol and Hepsiburada URLs are read without their seller or size parameters: the row is the page's default variant and featured seller.
- Çiçeksepeti rows cover both marketplace products and its own flower and gift products.
- PttAVM writes the seller name into its brand field. The Actor does not export that as a brand.
- Amazon Türkiye rows come from the search page unless "Include every seller" is on, because its product pages are heavy and carry no barcode. At most 20 Amazon product pages are read per run: further search results keep their search-page data, further Amazon product URLs are skipped, and the run message and `SUMMARY` say how many.
- Akakçe and Cimri prices are what those sites list. They can be older than the marketplace page. Cimri serves cached pages, so one run can read an older copy and the next run a refreshed one; the difference is then reported as a change.
- The Actor uses plain HTTP requests. It does not log in, does not solve CAPTCHAs or bot checks, and does not use private APIs. A source that asks for verification is reported as blocked for that run.
- Requests go only to the listed marketplace domains. URLs on other domains are skipped and listed in the summary.
- Maximum per run: 50 queries, 500 URLs, 100 results per marketplace and query.

### Changelog

- **1.0** (October 2026). First version. Region TR. Trendyol, Hepsiburada, n11, Pazarama, Çiçeksepeti, PttAVM, Akakçe and Cimri supported, Amazon Türkiye in beta. Product matching, price comparison and change tracking.

### Legal and privacy

The Actor reads publicly visible product, price, seller-store and availability data. It collects no customer data: no review texts, no reviewer names or profiles. Seller data is limited to the store name, store id, store page and store score shown on the marketplace; seller legal details such as tax numbers, addresses, e-mail addresses and phone numbers are not collected even where a page shows them. It performs no purchases and uses no accounts.

You are responsible for using the data in line with the terms of the sites and the laws that apply to you. This Actor is not affiliated with Trendyol, Hepsiburada, Amazon, n11, Pazarama, Çiçeksepeti, PttAVM, Akakçe or Cimri.

### Support

Found a wrong price, a wrong match or a source that stopped working? Open an issue on the Issues tab with the run id. The `SUMMARY` record of that run shows what each source returned.

# Changelog

This Actor's version history is a separate document: https://apify.com/akatra/marketplace-price-intelligence/changelog.md

# Actor input Schema

## `searchQueries` (type: `array`):

Product names to search on every selected marketplace, for example "iPhone 16 128 GB". Be specific: every word of the query must appear in a listing for it to be returned. Up to 50 queries per run.

## `startUrls` (type: `array`):

Optional. Product pages (or search-result pages) on a supported marketplace or comparison site. Each URL is routed to its marketplace automatically; URLs on any other domain are skipped and listed in the run summary. Use product URLs to track specific products.

## `marketplaces` (type: `array`):

Where to search. Leave empty to use every fully supported marketplace of the region. Akakçe and Cimri are price-comparison sites, not marketplaces: their rows are labelled sourceType = comparison_source. Amazon Türkiye is BETA: it often answers with a bot check, which is reported and never bypassed, and at most 20 of its product pages are read per run.

## `maxResultsPerMarketplace` (type: `integer`):

How many products to take from each marketplace for each query (1-100). Sellers of one product do not count against this limit.

## `compareAcrossMarketplaces` (type: `boolean`):

Open each product page to read its barcode (GTIN), seller and stock, group identical products across marketplaces and add lowest price, price difference and cheapest marketplace to every safely matched row. Turn off for a faster listing-only run.

## `includeSellers` (type: `boolean`):

Return one row per seller of a product (where the marketplace shows other sellers) instead of only the featured seller. On comparison sites this returns every listed shop offer instead of only the cheapest.

## `monitorKey` (type: `string`):

Optional name of a tracking job, for example "phones-daily". Runs with the same key are compared with each other: the first run stores a baseline, later runs report price, stock and seller changes. Different keys never share history.

## `onlyChanged` (type: `boolean`):

After the baseline run, return only new offers and offers whose price, stock or seller changed. Unchanged offers are not written to the dataset and are not charged. Without a monitor key, a key is derived from the queries, URLs and marketplaces.

## `priceChangeThresholdPercent` (type: `integer`):

Ignore price changes smaller than this percentage (0 = report every change). Stock and seller changes are always reported.

## `region` (type: `string`):

Market to work in. Version 1 supports Türkiye (TR). Prices are never compared across regions or currencies.

## Actor input object example

```json
{
  "searchQueries": [
    "iPhone 16 128 GB"
  ],
  "marketplaces": [
    "trendyol_tr",
    "hepsiburada_tr",
    "n11_tr",
    "pazarama_tr",
    "ciceksepeti_tr",
    "pttavm_tr"
  ],
  "maxResultsPerMarketplace": 10,
  "compareAcrossMarketplaces": true,
  "includeSellers": false,
  "onlyChanged": false,
  "priceChangeThresholdPercent": 0,
  "region": "TR"
}
```

# Actor output Schema

## `offers` (type: `string`):

One row per offer: marketplace, title, price, seller, stock, product group and comparison fields.

## `comparison` (type: `string`):

The same rows with the cross-marketplace comparison columns first.

## `changes` (type: `string`):

The same rows with the change-tracking columns first (useful with a monitor key).

## `offersFull` (type: `string`):

Every field of every row.

## `summary` (type: `string`):

Queries and URLs processed, offers found and written, matched and unmatched products, changes, health of every marketplace adapter, requests, cache hits and warnings.

# 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 = {
    "searchQueries": [
        "iPhone 16 128 GB"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("akatra/marketplace-price-intelligence").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 = { "searchQueries": ["iPhone 16 128 GB"] }

# Run the Actor and wait for it to finish
run = client.actor("akatra/marketplace-price-intelligence").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 '{
  "searchQueries": [
    "iPhone 16 128 GB"
  ]
}' |
apify call akatra/marketplace-price-intelligence --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,akatra/marketplace-price-intelligence"
        }
    }
}
```

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/ohKtbO8hfjOiFM8OA/builds/ZHbdzMd7GHTLZKBJL/openapi.json
