# Trendyol Scraper — Turkey Product Prices, Discounts & Ratings (`zinin/trendyol-scraper`) Actor

Search Trendyol — Turkey's largest marketplace — by keyword or search URL and get product listings: price in TRY with real discount %, brand, category, rating, review count, seller and delivery flags. No login required.

- **URL**: https://apify.com/zinin/trendyol-scraper.md
- **Developed by:** [Tim Zinin](https://apify.com/zinin) (community)
- **Categories:** E-commerce, Automation
- **Stats:** 2 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?

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

## Trendyol Scraper — Turkey Product Prices, Discounts and Ratings

Get live Trendyol search results as clean rows: price in TRY with the real discount %, brand, category, rating, review count, seller and delivery flags, and the direct product URL — for any keyword or search URL, no Trendyol account needed.

![Trendyol Scraper — what goes in and what comes out](https://raw.githubusercontent.com/TimmyZinin/apify-actor-assets/edf228c422129f57e34bbc7ffa4f3551f101b7db/travel-mkt-10/trendyol-scraper/readme-hero.webp)

![Trendyol Scraper — automation workflow](https://raw.githubusercontent.com/TimmyZinin/apify-actor-assets/edf228c422129f57e34bbc7ffa4f3551f101b7db/travel-mkt-10/trendyol-scraper/readme-workflow.webp)

Trendyol is Turkey's largest online marketplace: thousands of merchants sell through one search box, and the same product often shows up from several sellers at different prices, with campaign discounts that change by the hour. This Actor reads the public search results pages exactly as a shopper in Turkey sees them and turns every product card into one structured row. You choose the keywords (Turkish or English) or paste a search URL with your own filters, set how many products you need, and get a dataset you can download as JSON, CSV or Excel, pull through the Apify API, or send to Google Sheets, Make, n8n, Zapier or an AI agent over MCP.

It is built for recurring price and assortment work: run it daily on the same keywords, compare the rows, and you know who dropped a price, who launched a campaign discount and which seller is gaining reviews.

### What you get

One row per product card on the Trendyol search results page:

- **Product identity** — `productId` (Trendyol's internal id, stable across runs), full product `title`, `brand`, `category` and direct `url` on www.trendyol.com.
- **Price** — `price` as a number in Turkish lira (`currency` is always `TRY`), exactly the amount a buyer pays right now.
- **Real discounts only** — `originalPrice` and `discountPercent` are filled in only when Trendyol shows a crossed-out price on the card. A product whose price simply differs from Trendyol's reference "recommended retail price" (with no visible strikethrough) is **not** reported as discounted — this Actor matches what a shopper actually sees, not every internal price field Trendyol ships.
- **Social proof** — `rating` (0–5) and `reviewCount`, plus `favoriteCount` and `orderCount` badges (e.g. `"243K"`, `"1000+"`) exactly as Trendyol renders them.
- **Seller** — `merchantId` (Trendyol's internal seller id) and `officialSeller`, true when the card carries Trendyol's official-seller badge. Trendyol's search cards do not expose a seller display name, so there is no `sellerName` field — only the id and the badge, which is what the card itself shows.
- **Delivery and shipping** — `freeShipping` and `fastDelivery` (rush, next-day or same-day delivery flags merged into one boolean).
- **Merchandising signals** — `bestSellerRank` (Trendyol's numbered best-seller badge, when shown), `badges` (other card tags such as "Hesaplı Ürünler"), `variant` (colour/size when the product is not a single-size item).
- **Ad transparency** — `isSponsored` marks paid placements. They are excluded by default; switch **Include sponsored listings** on to see which sellers are buying visibility for your keyword.
- **Position** — `page` and `position` on the results page, so you can track ranking over time.
- **Context** — the `query` or `searchUrl` that produced the row and `scrapedAt` timestamp.

Every row is a real product that Trendyol showed for your search. Blocked pages and spending-limit stops are reported as **free** rows with an `error` field, so you always know what happened and never pay for an explanation.

### Who uses it

- **Cross-border sellers and importers** checking what Turkish sellers charge for a product before they list it, and who dominates a keyword.
- **Brands and distributors** watching authorised and unauthorised resellers of their products on Trendyol: price floors, campaign discounts, official-seller coverage.
- **E-commerce and pricing teams** feeding a repricing tool or a BI dashboard with daily Trendyol prices next to Hepsiburada and Amazon Turkey data.
- **Market researchers and analysts** sizing a category: how many sellers, what price band, how reviews are distributed, how much of page one is sponsored.
- **Affiliate and content publishers** building "best wireless earbuds under 500 TL" style pages from fresh prices, review counts and product links.
- **AI agents** that need a grounded answer about current Turkish retail prices and can call the Actor as an MCP tool.

### How to run

1. Click **Try for free** (or **Start**) on this page. You need a free Apify account; no Trendyol account, no API key.
2. In **Search keywords**, enter one or more keywords, one per line. Turkish works best for Turkish products (`kulaklık`, `kadın elbise`), English brand and model names work too (`iphone 15`, `nike air max`).
3. Optional: paste one or more Trendyol search or category URLs into **Trendyol search or category URLs** to reuse filters you already set on the site (price range, brand, category). The Actor keeps every parameter of the URL and only walks its pages.
4. Pick a **Sort order** (best match, price, newest, best seller, most favourited, most rated) and set **Max products per keyword or URL**. One results page holds 36 products.
5. Click **Start**. The prefilled example (`iphone 15`, 20 products) finishes in under a minute.
6. Open the **Output** tab: the *Products* view shows image, title, price, discount, brand, rating and link; the *Errors and empty searches* view shows the free explanation rows. Download as JSON, CSV, Excel or HTML, or call the dataset through the API.

To run it on a schedule, open **Schedules**, pick the Actor (or a saved task with your keywords) and choose daily or hourly. To connect it to other tools, see [Integration recipes](#integration-recipes).

### Pricing

This Actor uses **pay per event** pricing. You pay only for products actually delivered to your dataset, plus a small start fee:

| Event | Price | When it is charged |
|---|---|---|
| Actor start | $0.02 per GB of memory | Once per run. |
| Product found | $0.0015 per product | For every product row delivered to the dataset. |

**Example:** with the default 2 GB memory, a run that delivers 100 products costs 2 × $0.02 + 100 × $0.0015 = **$0.19**; 1,000 products cost **$1.54**. The same price applies on every Apify plan.

What you do **not** pay for:

- Rows with an `error` field — pages Trendyol did not return, and the note written when your spending limit is reached — are free.
- Proxy traffic, browser time and retries are included in the product price. You never see a separate proxy bill.
- Sponsored listings are only delivered (and charged) when you switch **Include sponsored listings** on.

**Spending limit.** Apify lets you set *Max total charge* for any run. The Actor checks the remaining budget **before** every product and stops cleanly when the next product would exceed it, then writes a free row saying so.

**Free plan.** Apify's free plan includes monthly platform credit that covers small test runs of this Actor. The prefilled example is sized so that it completes well inside that credit.

### Input contract

| Field | Type | Default | What it does |
|---|---|---|---|
| `searchQueries` | array of strings | — (prefill `["iphone 15"]`) | Keywords to search on www.trendyol.com. One run can hold up to 50 keywords; duplicates are removed. |
| `startUrls` | array of URLs | `[]` | Trendyol search or category URLs (`https://www.trendyol.com/...`). Filters in the URL are kept, except pagination, which the Actor drives itself. Other hosts are rejected before any work starts. |
| `sort` | string | `SCORE` | `SCORE` (best match), `PRICE_BY_ASC`, `PRICE_BY_DESC`, `MOST_RECENT`, `BEST_SELLER`, `MOST_FAVOURITE`, `MOST_RATED`. Applied to keywords only. |
| `maxItemsPerQuery` | integer 1–3000 | 36 (prefill 20) | Products to return per keyword or URL. The Actor stops paginating as soon as the limit is reached. |
| `includeSponsored` | boolean | `false` | Deliver sponsored placements too, flagged with `isSponsored: true`. |

You must provide at least one keyword or one URL. An empty input fails immediately with a clear message and costs nothing beyond the start event.

**Minimal input (the prefill):**

```json
{
  "searchQueries": ["iphone 15"],
  "maxItemsPerQuery": 20
}
```

**Price research input — cheapest first, several keywords:**

```json
{
  "searchQueries": ["kulaklık", "kadın elbise", "spor ayakkabı"],
  "sort": "PRICE_BY_ASC",
  "maxItemsPerQuery": 120,
  "includeSponsored": false
}
```

**Reuse filters you set on the site:**

```json
{
  "startUrls": [
    { "url": "https://www.trendyol.com/sr?q=kulakl%C4%B1k&sst=BEST_SELLER" }
  ],
  "maxItemsPerQuery": 36
}
```

### Output examples

All examples below are copied from real runs of this Actor on the Apify platform (September 2026). Nothing is invented or edited except whitespace.

#### Happy output

Input `{"searchQueries": ["iphone 15"], "maxItemsPerQuery": 12}` — run finished in 37 seconds, 12 products delivered, 0 errors. First row:

```json
{
  "productId": "762254881",
  "title": "iPhone 15 128 GB Mavi",
  "brand": "Apple",
  "category": "IOS Cep Telefonları",
  "price": 56999,
  "originalPrice": null,
  "discountPercent": null,
  "currency": "TRY",
  "rating": 4.643522833178006,
  "reviewCount": 2146,
  "favoriteCount": "243K",
  "orderCount": "100+",
  "merchantId": "968",
  "officialSeller": true,
  "freeShipping": false,
  "fastDelivery": true,
  "bestSellerRank": 1,
  "badges": ["Hesaplı Ürünler"],
  "variant": null,
  "isSponsored": false,
  "imageUrl": "https://cdn.dsmcdn.com/mnresize/400/-/ty1609/prod/QC/20241202/09/d1662cea-116d-3e2c-9a7a-66c6204ea0a3/1_org_zoom.jpg",
  "url": "https://www.trendyol.com/apple/iphone-15-128-gb-mavi-p-762254881",
  "page": 1,
  "position": 1,
  "query": "iphone 15",
  "searchUrl": "https://www.trendyol.com/sr?q=iphone+15",
  "scrapedAt": "2026-09-25T16:53:11.000Z"
}
```

A larger real run — `{"searchQueries": ["kulaklık"], "maxItemsPerQuery": 120}` — walked seven results pages and delivered all 120 products in 149 seconds, including live campaign discounts:

```json
{
  "productId": "855229295",
  "title": "Redmi Buds 6 Play Siyah Kulakiçi Kulaklık-Gürültü Önleme BT5.4 IOS&Android (Xiaomi TR Garantili)",
  "brand": "Xiaomi",
  "category": "Kulak içi TWS Bluetooth Kulaklık",
  "price": 734.02,
  "originalPrice": 749,
  "discountPercent": 2,
  "currency": "TRY",
  "rating": 4.349005334795832,
  "reviewCount": 20057,
  "favoriteCount": "249K",
  "orderCount": "1000+",
  "merchantId": "624588",
  "officialSeller": true,
  "freeShipping": true,
  "fastDelivery": true,
  "bestSellerRank": 2,
  "badges": ["Avantajlı Ürün"],
  "variant": null,
  "isSponsored": false,
  "imageUrl": "https://cdn.dsmcdn.com/mnresize/400/-/ty1797/prod/QC_PREP/20251207/22/be037857-44fe-369d-968e-6dc2f928f52b/1_org_zoom.jpg",
  "url": "https://www.trendyol.com/xiaomi/redmi-buds-6-play-siyah-kulakici-kulaklik-gurultu-onleme-bt5-4-ios-android-xiaomi-tr-garantili-p-855229295",
  "page": 1,
  "position": 1,
  "query": "kulaklık",
  "searchUrl": "https://www.trendyol.com/sr?q=kulakl%C4%B1k",
  "scrapedAt": "2026-09-25T16:55:19.818Z"
}
```

#### Failure output

When Trendyol does not return a usable results page after three fresh residential sessions — for example, a URL with an unsupported filter combination that keeps re-triggering the site's challenge page — the job gets a free error row and, if every job in the run failed, the run still ends as **Succeeded** with the status message "The site blocked all N search(es)… No result was billed, only the run start." — check that message or the `error` field to retry automatically:

```json
{
  "productId": null,
  "title": null,
  "brand": null,
  "price": null,
  "currency": "TRY",
  "url": null,
  "query": null,
  "searchUrl": "https://www.trendyol.com/sr?q=iphone+15&prc=999000000-999999999",
  "error": "https://www.trendyol.com/sr?q=iphone+15&prc=999000000-999999999: The site did not return a result page after 3 attempts (last HTTP 403, title \"Arama Sonuçları - Trendyol\").",
  "scrapedAt": "2026-09-25T17:00:31.206Z"
}
```

No product was charged for that job; only the start event and the successfully delivered keywords in the same run applied. Note on true "no results" keywords: Trendyol's own search almost never returns zero products for a text query — instead it falls back to related items for the closest match it can find, the same behaviour you see typing a nonsense term into the site's own search box. The free `No results found for "…".` row exists in this Actor as a safety net (for example, a pasted category URL that is genuinely empty), but a plain keyword search essentially always returns something.

### Field dictionary

| Field | Type | Meaning | Notes |
|---|---|---|---|
| `productId` | string | Trendyol's internal product id | Use it as the primary key when you compare runs. `null` only on error rows. |
| `title` | string | Product title exactly as the seller wrote it | Turkish or English depending on the listing. Not translated. |
| `brand` | string | Brand name | Falls back to Trendyol's web-brand field when the plain brand is missing. |
| `category` | string | Trendyol's leaf category name for the product | Turkish. |
| `price` | number | Price a buyer pays right now, in lira | The card's `discountedPrice` when present, otherwise its current price. |
| `originalPrice` | number | Crossed-out "was" price | Only set when Trendyol shows a real strikethrough on the card; `null` otherwise, including when Trendyol's internal reference price differs from the current price without a visible discount badge. |
| `discountPercent` | integer | Discount vs. `originalPrice` | Computed from the two prices; matches the percentage badge Trendyol shows. |
| `currency` | string | Always `TRY` | Present on every row, including error rows, for schema stability. |
| `rating` | number | Average rating, 0–5 | `null` when the item has no ratings yet. |
| `reviewCount` | integer | Number of ratings for the item | |
| `favoriteCount` | string | Favourites badge as Trendyol renders it | Already abbreviated by Trendyol (e.g. `"243K"`); `null` when not shown. |
| `orderCount` | string | Orders badge as Trendyol renders it | E.g. `"100+"`, `"1000+"`; `null` when not shown. |
| `merchantId` | string | Trendyol's internal seller id | No seller display name is available on the search card. |
| `officialSeller` | boolean | Card carries Trendyol's official-seller badge | |
| `freeShipping` | boolean | Card shows free shipping | |
| `fastDelivery` | boolean | Rush, next-day or same-day delivery flag | Merged from Trendyol's three separate delivery flags. |
| `bestSellerRank` | integer | Numbered best-seller badge (e.g. `1`) | `null` when the card has no best-seller badge. |
| `badges` | array of strings | Other merchandising tags on the card | Internal Trendyol tag codes are filtered out; only human-readable tags remain. |
| `variant` | string | Colour/size variant | `null` for single-size products. |
| `isSponsored` | boolean | Paid placement | Only `true` when **Include sponsored listings** is on. |
| `imageUrl` | string | Product image (CDN) | Images are not downloaded by the Actor; the URL is Trendyol's. |
| `url` | string | Product page on www.trendyol.com | Query-string tracking parameters are stripped. |
| `page` | integer | Results page the product appeared on | 1-based. |
| `position` | integer | Position on that page | 1-based, organic order after filtering sponsored rows. |
| `query` | string | Keyword that produced the row | `null` for URL inputs. |
| `searchUrl` | string | First results page URL for this keyword or URL | |
| `scrapedAt` | string | ISO timestamp when the row was written | UTC. |
| `error` | string | Present only on free explanation rows | Never present on paid product rows. |

### Evidence and boundaries

What this Actor observes and what it does not:

- **Source.** Only the public Trendyol search results pages at `www.trendyol.com`, the same pages any visitor in Turkey sees without logging in. It does not open individual product pages, carts or account areas.
- **Price is the card price at run time.** Trendyol runs frequent flash campaigns and basket promotions. The row is what the search card said when the Actor loaded it, not a checkout total, and does not include coupons or Trendyol Plus member pricing.
- **Discount is what the card shows, not every internal field.** Trendyol's product data carries several price references (recommended retail price, campaign price, "current" price); this Actor reports a discount only when the card itself displays a crossed-out price, which is what a real shopper sees and trusts.
- **Ranking depends on context.** Relevance order can vary with location, time and personalisation. The Actor uses a Turkish residential connection and no login, which is the closest thing to a neutral shopper view, but two runs minutes apart can order page one differently.
- **No guarantees about completeness.** Broad keywords report tens of thousands of matches but only let visitors page through a bounded subset. For broad keywords, narrow the search (brand, price range in a pasted URL) rather than asking for tens of thousands of rows.
- **Titles are not translated or cleaned.** You get them exactly as the seller wrote them.

How the Actor reaches the page: Trendyol, like most large retailers, protects its pages behind a managed challenge. The Actor opens each results page in a real, privacy-hardened browser through Turkish residential proxies, waits for the challenge to clear and Trendyol's own page data to be present, and reads it. Images, fonts and video are never downloaded, which keeps the run fast and the traffic small. If a page is not usable, it retries with a fresh session up to three times and then reports the job as a free error row instead of guessing.

### Decision routing

| What you see in the data | What it usually means | What to do next |
|---|---|---|
| Your product appears from many sellers within a 5–10% price band | Commodity competition; price is the main lever | Track daily and alert on the lowest price per `productId` group |
| One seller sells well below everyone else | Clearance, grey import, or pricing error | Check the product page and seller history before matching the price |
| `discountPercent` spikes across a category on the same day | Trendyol-wide campaign (flash sale, basket promotion) | Compare your price against the campaign window, not a single snapshot |
| `officialSeller: false` for the market leader | An unauthorised or marketplace reseller is winning the keyword | Cross-check with your authorised dealer list |
| Many `isSponsored` rows for a keyword (with sponsored on) | Competitive, ad-driven keyword | Budget for ads or target long-tail keywords instead |
| `reviewCount` growing fast for a new `productId` | A rising product or a seller running a review campaign | Add the item to a watch list; compare against your listing |
| Free error row about attempts | Trendyol did not serve the page to three sessions | Re-run later; it is not charged |

### Commercial playbooks

**1. Daily price watch for a product line.** Save a task with your 10–30 product keywords, `sort: PRICE_BY_ASC` and `maxItemsPerQuery: 36`. Schedule it daily. In your sheet, group by `productId`, keep the minimum `price` per day, and alert when a competitor drops below your floor.

**2. Reseller and MAP monitoring for brands.** Search your brand name and model numbers. Group rows by `merchantId`. Sellers that are not `officialSeller: true`, or that sell under your minimum advertised price, are your follow-up list. Store `url` and `scrapedAt` as evidence.

**3. Category sizing before entering the Turkish market.** Run one broad keyword per sub-category with `maxItemsPerQuery: 300` and `sort: SCORE`. Count distinct sellers, look at the price distribution and the share of items with `officialSeller: true`. This tells you in an afternoon whether the category is fragmented or dominated.

**4. Campaign tracking.** Trendyol's flash sales and basket promotions change prices for hours, not days. Run the same task hourly during a campaign window and compare `price` and `discountPercent` to the pre-campaign baseline to see who actually discounts and who only relabels.

**5. Content and affiliate pages.** Pull the top products by `sort: MOST_RATED` for a keyword, filter to `reviewCount` above a threshold, and use the fresh price, rating and product link in your comparison page. Refresh weekly.

### Integration recipes

**Apify API (any language).** Start a run and get items in one call:

```bash
curl -X POST "https://api.apify.com/v2/acts/zinin~trendyol-scraper/run-sync-get-dataset-items?token=YOUR_APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"searchQueries": ["kulaklık"], "maxItemsPerQuery": 36, "sort": "PRICE_BY_ASC"}'
```

**Python client.**

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("zinin/trendyol-scraper").call(run_input={
    "searchQueries": ["kadın elbise"],
    "maxItemsPerQuery": 90,
})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    if not item.get("error"):
        print(item["price"], item["brand"], item["url"])
```

**JavaScript client.**

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

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('zinin/trendyol-scraper').call({ searchQueries: ['iphone 15'], maxItemsPerQuery: 36 });
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items.filter((i) => !i.error).length, 'products');
```

**Google Sheets.** Use Apify's Google Sheets integration on a saved task: every finished run appends rows to your sheet. Filter out rows where `error` is not empty.

**Make, n8n and Zapier.** Use the Apify app: trigger "Watch Actor runs" (or "Watch task runs"), then "Get dataset items", then your action — Slack message when the minimum price drops, a row in Airtable, a record in your CRM.

**Webhooks.** Add a webhook for `ACTOR.RUN.SUCCEEDED` pointing at your endpoint; it receives the run object with `defaultDatasetId`, and you fetch items from there.

**AI agents (MCP).** The Actor is available as a tool through the Apify MCP server (`https://mcp.apify.com`). An agent can call it with a keyword and use the returned rows to answer "what does X cost on Trendyol right now". Keep `maxItemsPerQuery` small for interactive use.

### Comparing runs over time

Most buyers use this Actor to see change, not a single snapshot. A reliable change-detection setup looks like this:

1. **Fix the input.** Save a task with the exact keywords, sort order and `maxItemsPerQuery`. Changing any of them changes which products are in scope and makes day-to-day comparison noisy.
2. **Key on `productId`.** Trendyol keeps it stable for the life of a listing. Titles and badges change with every campaign; positions move every hour.
3. **Store `scrapedAt` with every row.** It is the observation time. Two rows with the same `productId` and different `price` are a price change between those two timestamps.
4. **Separate "missing" from "out of stock".** If a `productId` disappears from the results, it may have dropped out of the page window you requested rather than sold out. This Actor does not currently report a stock flag; for important items, request more pages so the item stays in scope.
5. **Compare like with like.** Relevance order moves; if you need a stable universe, use `sort: PRICE_BY_ASC` or a pasted URL restricted to a category and brand.
6. **Watch `discountPercent`, not only price.** During campaigns some sellers raise the reference price and discount from there. A jump in `discountPercent` without a drop in `price` is worth a second look.

A simple daily sheet: one tab per day of rows, a pivot of minimum `price` per `productId`, and a conditional format that highlights a drop of more than 5%. That is enough to catch most competitor moves on Trendyol within a day.

**Typical signals worth an alert:** a new `merchantId` appearing in the top 10 for your brand keyword; the cheapest price for a `productId` group falling below your floor; `discountPercent` jumping for a competitor's flagship product; `reviewCount` jumping by more than 20 in a week for a competitor item.

### Operating guide

- **Memory.** The default is enough; more memory does not make pages load faster and increases the start fee.
- **Run size.** One results page = 36 products and a few seconds once the site's challenge has cleared for the session. A run with 10 keywords × 36 products typically finishes in a few minutes.
- **Scheduling.** Daily is enough for most price work; hourly makes sense only during campaign windows.
- **Stable keys.** Compare runs on `productId`, not on `title` (sellers edit titles constantly) and not on `position` (ranking moves).
- **Many keywords.** Put up to 50 keywords into one run rather than starting 50 runs — you pay one start fee instead of fifty.
- **Timeouts.** The default run timeout is 30 minutes. For very large jobs (thousands of products), raise the timeout or split keywords across runs.
- **Retries.** A job that failed with an attempts error is safe to run again; nothing was charged for it.

### Troubleshooting

**The run finished but I got fewer products than `maxItemsPerQuery`.** Trendyol had fewer matching products, or only lets visitors page through part of a very broad result set. Narrow the search with a pasted URL (brand, price range) to reach deeper items.

**My results look unrelated to my keyword.** Trendyol's own search substitutes the closest match it can find when your exact term has no hits — the Actor reports exactly what the site returned, the same as typing the term into trendyol.com yourself.

**I see an error about attempts.** Trendyol did not serve a usable page to three separate sessions. This is rare and temporary, and more likely on a pasted URL with an unusual filter combination; start the run again with the plain keyword or URL. The failed job was not charged.

**The run stopped early with a spending-limit row.** Your *Max total charge* was reached. Raise it in the run options or lower `maxItemsPerQuery`.

**Prices look different from what I see in my browser.** Your browser may be logged in (Trendyol Plus, personal coupons) or outside Turkey. The Actor sees Trendyol as a logged-out shopper in Turkey at the moment of the run.

**My pasted URL was rejected.** Only `https://www.trendyol.com/...` search or category URLs are accepted. Product pages and seller storefront pages are not search result pages.

### FAQ

**Do I need a Trendyol account or seller API access?** No. The Actor reads public search pages; there is nothing to register.

**Is this Trendyol's official API?** No. It is an independent tool that reads the public website. Trendyol's Marketplace API is for registered sellers managing their own listings and requires a seller account; this Actor needs neither and returns what any shopper's browser shows.

**Can I get product descriptions, all images or full variant lists?** Not in this Actor. It reads search results, which is what price and assortment work needs at scale. The `url` field takes you to the product page.

**How fresh is the data?** It is read at run time. Schedule the Actor as often as you need fresh prices.

**Can I search other Trendyol country sites (Trendyol Azerbaijan, Trendyol Germany)?** No, this Actor covers www.trendyol.com (Turkey) only.

**Can I run it from outside Turkey?** Yes. The Actor always uses a Turkish residential connection, so your own location does not matter.

**What happens if Trendyol changes its page?** Rows would stop appearing and jobs would return free error rows rather than wrong data. The Actor is monitored and updated.

### Türkçe açıklama (Trendyol Scraper)

Trendyol arama sonuçlarını, anahtar kelime veya arama URL'sinden otomatik olarak çeken bir araçtır. Trendyol hesabı veya API anahtarı gerekmez.

- **Elde edilen veriler:** ürün adı, fiyat (TL) ve gerçek indirim yüzdesi, marka, kategori, puan ve değerlendirme sayısı, favori/sipariş rozetleri, satıcı bilgisi (resmi satıcı rozeti), kargo ve hızlı teslimat bayrakları, ürün ve görsel URL'si, arama sıralaması.
- **Kullanım:** "Search keywords" alanına "kulaklık", "kadın elbise", "iphone 15" gibi anahtar kelimeleri her satıra bir tane olacak şekilde girin, kaç ürün istediğinizi (Max products) belirleyin ve "Start" butonuna basın. trendyol.com üzerinde filtrelediğiniz bir arama veya kategori URL'sini de doğrudan yapıştırabilirsiniz.
- **Sıralama:** varsayılan (en uygun), fiyata göre artan/azalan, en yeni, çok satan, favori ve en çok değerlendirilen sıralamalarını destekler.
- **Fiyatlandırma:** getirilen her ürün için kullanım başına ücretlendirme. Sonuç bulunamayan veya engellenen istekler için satır ücretsizdir.
- **Kullanım alanları:** fiyat takibi, rakip satıcı izleme, kategori pazar araştırması, satış ortaklığı (affiliate) içerikleri için güncel fiyat verisi.
- **Çıktı formatları:** JSON, CSV, Excel. Google E-Tablolar, Make, n8n, Zapier ve API entegrasyonlarıyla uyumludur.

Arama örnekleri: trendyol fiyat takibi, trendyol veri çekme, trendyol ürün listesi CSV, trendyol rakip fiyat izleme, trendyol indirim takibi.

### Sources and rights

- Data comes from publicly accessible Trendyol search result pages. The Actor does not log in, does not bypass paywalls and does not collect personal data about shoppers; seller ids are business identifiers published by Trendyol.
- Product titles, prices and images belong to Trendyol and the respective sellers. Use the data in line with Trendyol's terms and the laws that apply to you, especially for republication. For large-scale commercial reuse or seller-side data, consider Trendyol's official Marketplace API.
- This Actor is not affiliated with, endorsed by or sponsored by Trendyol. "Trendyol" is a trademark of its owner and is used here only to describe the data source.
- Report a bug or ask for a feature in the **Issues** tab of this Actor. Custom fields or other Turkish marketplaces can be built on request.

### More marketplace scrapers from the same author

| Actor | What it gives you |
|---|---|
| [Mercado Libre Scraper](https://apify.com/zinin/mercadolibre-scraper) | Latin American product prices and sellers |
| [Rakuten Ichiba Scraper](https://apify.com/zinin/rakuten-scraper) | Japanese product prices, shops, reviews and points |
| [bol.com Scraper](https://apify.com/zinin/bol-scraper) | Dutch and Belgian product prices and sellers |
| [Shopify Store Price & Catalog Change Monitor](https://apify.com/zinin/shopify-price-change-monitor) | Price and catalogue changes on Shopify stores |

# Actor input Schema

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

Keywords to search on www.trendyol.com. Turkish or English both work, e.g. "iphone 15", "kulaklık", "kadın elbise". One keyword per line.

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

Paste www.trendyol.com/sr?q=... search URLs, or category listing URLs, to reuse filters you set on the site (price range, brand, category). Leave empty when using keywords.

## `sort` (type: `string`):

Order of results for keyword searches. Ignored for pasted URLs, which keep their own sort.

## `maxItemsPerQuery` (type: `integer`):

How many products to return for each keyword or URL. One results page holds 36 products.

## `includeSponsored` (type: `boolean`):

Trendyol mixes paid (sponsored) product cards into search results. Off by default so you get organic results only; sponsored rows are flagged with isSponsored when included.

## Actor input object example

```json
{
  "searchQueries": [
    "iphone 15"
  ],
  "startUrls": [],
  "sort": "SCORE",
  "maxItemsPerQuery": 20,
  "includeSponsored": false
}
```

# Actor output Schema

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

Dataset items produced by this run.

# 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 15"
    ],
    "startUrls": [],
    "sort": "SCORE",
    "maxItemsPerQuery": 20,
    "includeSponsored": false
};

// Run the Actor and wait for it to finish
const run = await client.actor("zinin/trendyol-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 = {
    "searchQueries": ["iphone 15"],
    "startUrls": [],
    "sort": "SCORE",
    "maxItemsPerQuery": 20,
    "includeSponsored": False,
}

# Run the Actor and wait for it to finish
run = client.actor("zinin/trendyol-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 '{
  "searchQueries": [
    "iphone 15"
  ],
  "startUrls": [],
  "sort": "SCORE",
  "maxItemsPerQuery": 20,
  "includeSponsored": false
}' |
apify call zinin/trendyol-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,zinin/trendyol-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/zCKpfc0GRKzaiYxUc/builds/TtM7hScH8bfze3JwS/openapi.json
