{
  "openapi": "3.0.1",
  "info": {
    "title": "Motoinzerce Scraper",
    "description": "Scrape motorcycle listings from MotoInzerce.cz with engine size filtering. \nExtract full details: price, specs, photos, seller descriptions, phone/email. \nIdeal for market analysis, lead generation, and price monitoring of Czech \nmotorcycle inventory.",
    "version": "2.0",
    "x-build-id": "afGlZiNm6siWSBztD"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/gearshift-data~motoinzerce-scraper/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-gearshift-data-motoinzerce-scraper",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/acts/gearshift-data~motoinzerce-scraper/runs": {
      "post": {
        "operationId": "runs-sync-gearshift-data-motoinzerce-scraper",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor and returns information about the initiated run in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/runsResponseSchema"
                }
              }
            }
          }
        }
      }
    },
    "/acts/gearshift-data~motoinzerce-scraper/run-sync": {
      "post": {
        "operationId": "run-sync-gearshift-data-motoinzerce-scraper",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "inputSchema": {
        "type": "object",
        "properties": {
          "ingestMode": {
            "title": "Ingest mode",
            "enum": [
              "full",
              "incremental"
            ],
            "type": "string",
            "description": "• Full — scrape search results and fetch details for every listing.\n• Incremental — only fully scrape listings that weren't seen in previous runs. The actor remembers IDs in its key-value store and skips already-known listings. Summary records (title, price, url, year) are still produced for every listing so you can detect price changes across runs.",
            "default": "full"
          },
          "customUrl": {
            "title": "🔗 Custom Search URL (Optional)",
            "type": "string",
            "description": "Paste a MotoInzerce.cz URL to use as the starting point. If set, all filter fields below are ignored.\n\nBest for filtering by manufacturer, model, category, condition, or region — these use internal site IDs that can't be typed directly. To get the right URL: (1) go to motoinzerce.cz/hledat.php, (2) select your filters from the dropdowns, (3) click Hledat, (4) copy the URL from your browser's address bar.\n\nUse https://www.motoinzerce.cz/vypisy/ to scrape all listings with no filtering."
          },
          "keywords": {
            "title": "Keywords (Search in Title)",
            "type": "string",
            "description": "Search for text within listing titles. This is the easiest way to filter by manufacturer or model — just type the name and the scraper will only visit listings whose title matches. Leave empty to skip. Examples: 'honda cb 500', 'yamaha mt-07', 'kawasaki z900', 'enduro'"
          },
          "keywordsloc": {
            "title": "Search in",
            "enum": [
              "nazev",
              "popis",
              "vse"
            ],
            "type": "string",
            "description": "Which part of each listing to match keywords against. 'Title only' is the default and fastest. Use 'Title & description' for broader results.",
            "default": "nazev"
          },
          "minYear": {
            "title": "Vyrobeno Od (Year From)",
            "type": "integer",
            "description": "Only scrape motorcycles manufactured in or after this year. Leave empty for no minimum year filter."
          },
          "maxYear": {
            "title": "Vyrobeno Do (Year To)",
            "type": "integer",
            "description": "Only scrape motorcycles manufactured up to this year. Leave empty for no maximum year filter."
          },
          "minMileage": {
            "title": "Najeto Od (Mileage From)",
            "type": "integer",
            "description": "Minimum mileage in kilometers. Leave empty for no minimum mileage filter."
          },
          "maxMileage": {
            "title": "Najeto Do (Mileage To)",
            "type": "integer",
            "description": "Maximum mileage in kilometers. Leave empty for no maximum mileage filter."
          },
          "minPrice": {
            "title": "Cena Od (Price From)",
            "type": "integer",
            "description": "Minimum price in Czech Koruna (CZK). Leave empty for no minimum price filter."
          },
          "maxPrice": {
            "title": "Cena Do (Price To)",
            "type": "integer",
            "description": "Maximum price in Czech Koruna (CZK). Leave empty for no maximum price filter."
          },
          "minEngineCcm": {
            "title": "Objem Od (Engine From)",
            "type": "integer",
            "description": "Minimum engine displacement in ccm. Leave empty for no minimum engine size filter."
          },
          "maxEngineCcm": {
            "title": "Objem Do (Engine To)",
            "type": "integer",
            "description": "Maximum engine displacement in ccm. Leave empty for no maximum engine size filter."
          },
          "sorting": {
            "title": "Řazení (Sorting)",
            "enum": [
              "cenaa",
              "cenad",
              "datud"
            ],
            "type": "string",
            "description": "How to sort the search results.",
            "default": "cenaa"
          },
          "listingsPerPage": {
            "title": "Listings per page (Stránkování)",
            "enum": [
              "10",
              "20",
              "30",
              "50",
              "100"
            ],
            "type": "string",
            "description": "Number of listings shown per search result page. Higher values mean fewer pages to crawl for the same total results. Maps to the 'strankovani' URL parameter.",
            "default": "20"
          },
          "skipTipmoto": {
            "title": "Skip tipmoto.com promoted listings",
            "type": "boolean",
            "description": "Exclude promoted tipmoto.com dealer listings that appear inline in motoinzerce.cz search results. These rows have class 'tipmoto' or link to tipmoto.com.",
            "default": false
          },
          "scrapePhotos": {
            "title": "Extract photos from detail pages",
            "type": "boolean",
            "description": "Extract full-size photo URLs from the listing's photo gallery. Adds a 'photos' array and 'photoCount' to each item.",
            "default": true
          },
          "scrapeDescription": {
            "title": "Extract seller description from detail pages",
            "type": "boolean",
            "description": "Extract the full seller description text from each listing's detail page.",
            "default": true
          },
          "archivePhotos": {
            "title": "Archive photos to Cloudflare R2",
            "type": "boolean",
            "description": "Download each listing's gallery photos, resize them to WebP, and upload to a Cloudflare R2 bucket. Protects against photo loss when source listings end. Adds `photosArchived[]` to the output. Requires the R2 fields below.",
            "default": false
          },
          "r2AccountId": {
            "title": "R2 Account ID",
            "type": "string",
            "description": "Cloudflare account id — the subdomain of your R2 S3 endpoint."
          },
          "r2BucketName": {
            "title": "R2 Bucket name",
            "type": "string",
            "description": "Target R2 bucket.",
            "default": "gearshift-moto-photos"
          },
          "r2AccessKeyId": {
            "title": "R2 Access Key ID",
            "type": "string",
            "description": "R2 API token access key id. Use Apify secrets."
          },
          "r2SecretAccessKey": {
            "title": "R2 Secret Access Key",
            "type": "string",
            "description": "R2 API token secret. Use Apify secrets."
          },
          "r2PublicBaseUrl": {
            "title": "R2 Public base URL",
            "type": "string",
            "description": "Public URL prefix for archived photos, e.g. https://pub-abc123.r2.dev"
          },
          "r2MaxDimension": {
            "title": "Max dimension (px)",
            "minimum": 200,
            "maximum": 4000,
            "type": "integer",
            "description": "Resize each photo so its longer edge fits within this many pixels.",
            "default": 1200
          },
          "r2Quality": {
            "title": "WebP quality (1-100)",
            "minimum": 1,
            "maximum": 100,
            "type": "integer",
            "description": "WebP encoder quality.",
            "default": 80
          },
          "scrapePhone": {
            "title": "Extract seller phone number from detail pages",
            "type": "boolean",
            "description": "⚠️ PRIVACY / GDPR: Phone numbers are personal data. Under GDPR (and similar laws) you are the data controller for anything you collect — you are responsible for having a lawful basis, honoring data-subject rights, and not using the data for spam, profiling, or resale without consent. The operator of this Actor is not your data controller and does not assume that responsibility.\n\n🛡 PROXY REQUIRED: The motoinzerce.cz contact endpoint (/inzerat_zobrazeni.php) aggressively rate-limits by IP — after a few requests it returns an anti-scraping block image instead of the real contact. Enable Apify Proxy with group RESIDENTIAL below; datacenter and no-proxy runs get blocked quickly.\n\nFetches the seller's phone from each listing. The image is saved to the Key-Value store and 'phoneImage' contains a stable https://api.apify.com URL (base64 data URI when run locally). Each enabled listing makes 1 extra HTTP request.",
            "default": false
          },
          "scrapeEmail": {
            "title": "Extract seller email from detail pages",
            "type": "boolean",
            "description": "⚠️ PRIVACY / GDPR: Email addresses are personal data. Under GDPR (and similar laws) you are the data controller for anything you collect — you are responsible for having a lawful basis, honoring data-subject rights, and not using the data for spam, profiling, or resale without consent. The operator of this Actor is not your data controller and does not assume that responsibility.\n\n🛡 PROXY REQUIRED: The motoinzerce.cz contact endpoint (/inzerat_zobrazeni.php) aggressively rate-limits by IP — after a few requests it returns an anti-scraping block image instead of the real contact. Enable Apify Proxy with group RESIDENTIAL below; datacenter and no-proxy runs get blocked quickly.\n\nFetches the seller's email from each listing. The image is saved to the Key-Value store and 'emailImage' contains a stable https://api.apify.com URL (base64 data URI when run locally). Each enabled listing makes 1 extra HTTP request.",
            "default": false
          },
          "ocrContacts": {
            "title": "Convert phone/email images to plain text (OCR)",
            "type": "boolean",
            "description": "Runs on-device OCR (tesseract.js) on the phone and email images to populate the 'phone' and 'email' text fields with the actual number/address — in addition to the image URL. Requires scrapePhone and/or scrapeEmail to be enabled.\n\n💰 COST IMPACT (per listing): OCR is CPU-bound and adds roughly 200–600ms per image. A run with both scrapePhone and scrapeEmail enabled can take ~1s extra per listing, plus a one-time ~10MB language-data download and ~1–2s worker warm-up on startup. You will likely need more Actor memory (≥1024 MB recommended) and your run will be slower → more compute-unit cost. Only enable this if you actually need the plain-text values; otherwise keep the image URL alone.\n\n⚠️ PRIVACY / GDPR: Turning this on means you are no longer just storing an image — you are extracting and processing personal data (phone numbers, email addresses) in machine-readable form. The same GDPR responsibilities noted on 'scrapePhone' and 'scrapeEmail' apply and intensify here: lawful basis, purpose limitation, retention, and data-subject rights are entirely on you as the run operator. Do not enable unless you have decided that your use case is lawful.\n\nAccuracy is high on clean images but not guaranteed — always validate downstream.",
            "default": false
          },
          "maxPagesPerCrawl": {
            "title": "Max pages to crawl",
            "minimum": 0,
            "maximum": 999,
            "type": "integer",
            "description": "Maximum number of search result pages to scrape. Set to 0 for unlimited (scrape all available pages). Total listings = pages × listings per page.",
            "default": 10
          },
          "datasetName": {
            "title": "Dataset name (optional)",
            "type": "string",
            "description": "⚠️ IMPORTANT: When you use a named dataset, the run's default dataset will appear EMPTY. This is normal! Your data is stored in the named dataset instead. Access it via Storage → Datasets → [your dataset name].\n\nLeave empty to use the default run dataset (visible in the Dataset tab). Use named datasets to organize multiple runs or merge results across sessions. Example: 'honda-motorcycles-2024'"
          },
          "timeoutSecs": {
            "title": "Per-page timeout",
            "minimum": 30,
            "maximum": 3600,
            "type": "integer",
            "description": "Maximum time in seconds allowed for processing a single page. Increase if pages are slow to load or if you see frequent timeout errors.",
            "default": 120
          },
          "proxyConfiguration": {
            "title": "Proxy configuration",
            "type": "object",
            "description": "Select proxies to avoid being blocked by the website. Apify Proxy is recommended for reliable scraping. REQUIRED (with RESIDENTIAL group) if you enable scrapePhone, scrapeEmail, or ocrContacts — the contact endpoint blocks datacenter and no-proxy traffic after a few requests.",
            "default": {
              "useApifyProxy": true
            }
          },
          "maxRequestRetries": {
            "title": "Max request retries",
            "minimum": 0,
            "maximum": 10,
            "type": "integer",
            "description": "Maximum number of times to retry loading a page if it fails.",
            "default": 3
          },
          "maxConcurrency": {
            "title": "Max concurrency",
            "minimum": 1,
            "maximum": 50,
            "type": "integer",
            "description": "Maximum number of pages being processed simultaneously. Higher values = faster scraping but more resource usage.",
            "default": 10
          },
          "debugLog": {
            "title": "Debug logging",
            "type": "boolean",
            "description": "Enable detailed debug logs for troubleshooting. Warning: This will make logs very verbose.",
            "default": false
          },
          "maxItems": {
            "title": "Max items to scrape",
            "minimum": 0,
            "maximum": 999999,
            "type": "integer",
            "description": "Maximum total number of listings to scrape. Set to 0 for unlimited. This is useful for controlling costs when using PPE billing.",
            "default": 0
          }
        }
      },
      "runsResponseSchema": {
        "type": "object",
        "properties": {
          "data": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "actId": {
                "type": "string"
              },
              "userId": {
                "type": "string"
              },
              "startedAt": {
                "type": "string",
                "format": "date-time",
                "example": "2025-01-08T00:00:00.000Z"
              },
              "finishedAt": {
                "type": "string",
                "format": "date-time",
                "example": "2025-01-08T00:00:00.000Z"
              },
              "status": {
                "type": "string",
                "example": "READY"
              },
              "meta": {
                "type": "object",
                "properties": {
                  "origin": {
                    "type": "string",
                    "example": "API"
                  },
                  "userAgent": {
                    "type": "string"
                  }
                }
              },
              "stats": {
                "type": "object",
                "properties": {
                  "inputBodyLen": {
                    "type": "integer",
                    "example": 2000
                  },
                  "rebootCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "restartCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "resurrectCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "computeUnits": {
                    "type": "integer",
                    "example": 0
                  }
                }
              },
              "options": {
                "type": "object",
                "properties": {
                  "build": {
                    "type": "string",
                    "example": "latest"
                  },
                  "timeoutSecs": {
                    "type": "integer",
                    "example": 300
                  },
                  "memoryMbytes": {
                    "type": "integer",
                    "example": 1024
                  },
                  "diskMbytes": {
                    "type": "integer",
                    "example": 2048
                  }
                }
              },
              "buildId": {
                "type": "string"
              },
              "defaultKeyValueStoreId": {
                "type": "string"
              },
              "defaultDatasetId": {
                "type": "string"
              },
              "defaultRequestQueueId": {
                "type": "string"
              },
              "buildNumber": {
                "type": "string",
                "example": "1.0.0"
              },
              "containerUrl": {
                "type": "string"
              },
              "usage": {
                "type": "object",
                "properties": {
                  "ACTOR_COMPUTE_UNITS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_WRITES": {
                    "type": "integer",
                    "example": 1
                  },
                  "KEY_VALUE_STORE_LISTS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_INTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_EXTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_SERPS": {
                    "type": "integer",
                    "example": 0
                  }
                }
              },
              "usageTotalUsd": {
                "type": "number",
                "example": 0.00005
              },
              "usageUsd": {
                "type": "object",
                "properties": {
                  "ACTOR_COMPUTE_UNITS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_WRITES": {
                    "type": "number",
                    "example": 0.00005
                  },
                  "KEY_VALUE_STORE_LISTS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_INTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_EXTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_SERPS": {
                    "type": "integer",
                    "example": 0
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}