Install

Look up current shop prices for a product.

Finds a product on idealo's price comparison and returns its offers, cheapest first: shop, item price, price including shipping, the shop's offer title and delivery estimate, plus idealo's lowest and highest price and offer count. The product is the first idealo suggestion for the query (returned as output.product, so it can be checked). Runs only in the user's browser: idealo's Akamai protection rejects non-browser clients.

No reports yetRead-only, no login
Site
idealo, Germany
Version
v1
Runs, last 7 days
No reports yet
sha256
fccb30a97a7e…

Requests

sent from your browser, in order
  1. 1GETwww.idealo.de/suggest?max&qQuery to idealo product id (first /OffersOfProduct/ suggestion).
  2. 2GET{{steps.suggest.url}}Product page: JSON-LD aggregate offer and the first 20 offer rows.
  3. 3GETwww.idealo.de/offerpage/offerlist/product/{{steps.suggest.product_id}}/start/20/sort/default?excludeFilters&includeFiltersOffers 21-40 from the list fragment the 'Weitere Angebote' button loads.only when needed

Parameters

from your agent
max_offersenum20 = one page of offers, 40 = two 20 | 40 = 20
querystringrequiredProduct name, e.g. 'Sony WH-1000XM5', 'iPhone 16 128GB'

Returns

to your agent
categorystring
highest_price_eurnumber
lowest_price_eurnumber
offer_countintegerAll offers on idealo
offersobject[]delivery, offer_title, price_eur, shop, total_with_shipping_eur
productstringidealo product actually used
product_urlstring

Where it can send

  • www.idealo.de

Anything else is blocked by the extension.

Reads from your session

Nothing. Your browser attaches the site's cookies by itself.

Used only in requests to the addresses on the left. Never sent to wield.run or your agent.

Checks

a run passes when
  • length(output.offers) >= `10`
  • contains(output.product, 'WH-1000XM5')
  • output.lowest_price_eur > `50`
  • output.offers[0].price_eur >= output.lowest_price_eur
  • output.offers[0].total_with_shipping_eur >= output.offers[0].price_eur

Raw recipe

Served as canonical JSON from /api/v1/recipes/idealo.de/price-lookup, so its sha256 matches the ETag and the index.

Check it yourself
curl -s https://wield.run/api/v1/recipes/idealo.de/price-lookup | shasum -a 256
# fccb30a97a7e88508970bee10893d9ef8ea776de2f7d39c1ee7c20be411f1d90
idealo.de/price-lookup.json, v1
{
  "description": "Finds a product on idealo's price comparison and returns its offers, cheapest first: shop, item price, price including shipping, the shop's offer title and delivery estimate, plus idealo's lowest and highest price and offer count. The product is the first idealo suggestion for the query (returned as output.product, so it can be checked). Runs only in the user's browser: idealo's Akamai protection rejects non-browser clients.",
  "effect": "read",
  "id": "idealo.de/price-lookup",
  "keywords": [
    "idealo",
    "preisvergleich",
    "preis",
    "günstigster preis",
    "angebote",
    "shop vergleichen",
    "price comparison",
    "best price",
    "cheapest",
    "compare prices",
    "product price"
  ],
  "output": {
    "schema": {
      "properties": {
        "category": {
          "type": [
            "string",
            "null"
          ]
        },
        "highest_price_eur": {
          "type": [
            "number",
            "null"
          ]
        },
        "lowest_price_eur": {
          "type": [
            "number",
            "null"
          ]
        },
        "offer_count": {
          "description": "All offers on idealo",
          "type": [
            "integer",
            "null"
          ]
        },
        "offers": {
          "items": {
            "properties": {
              "delivery": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "offer_title": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "price_eur": {
                "type": [
                  "number",
                  "null"
                ]
              },
              "shop": {
                "type": "string"
              },
              "total_with_shipping_eur": {
                "type": [
                  "number",
                  "null"
                ]
              }
            },
            "type": "object"
          },
          "type": "array"
        },
        "product": {
          "description": "idealo product actually used",
          "type": "string"
        },
        "product_url": {
          "format": "uri",
          "type": "string"
        }
      },
      "required": [
        "product",
        "product_url",
        "offers"
      ],
      "type": "object"
    },
    "value": "{product: steps.suggest.name, category: steps.suggest.category && trim(replace(steps.suggest.category, 'in ', '')) || `null`, product_url: steps.suggest.url, lowest_price_eur: steps.product.low, highest_price_eur: steps.product.high, offer_count: steps.product.count, offers: [steps.product.offers[?shop != `null` && price_text != `null`].{shop: trim(split(shop, ' - Shop aus')[0]), price_eur: price_text && to_number(replace(replace(replace(split(price_text, ' ')[0], '.', ''), ',', '.'), '€', '')) || `null`, total_with_shipping_eur: shipping_text && to_number(replace(replace(replace(split(shipping_text, ' ')[0], '.', ''), ',', '.'), '€', '')) || `null`, offer_title: title, delivery: delivery} || `[]`, steps.more.offers[?shop != `null` && price_text != `null`].{shop: trim(split(shop, ' - Shop aus')[0]), price_eur: price_text && to_number(replace(replace(replace(split(price_text, ' ')[0], '.', ''), ',', '.'), '€', '')) || `null`, total_with_shipping_eur: shipping_text && to_number(replace(replace(replace(split(shipping_text, ' ')[0], '.', ''), ',', '.'), '€', '')) || `null`, offer_title: title, delivery: delivery} || `[]`][]}"
  },
  "params": {
    "additionalProperties": false,
    "properties": {
      "max_offers": {
        "default": 20,
        "description": "20 = one page of offers, 40 = two",
        "enum": [
          20,
          40
        ],
        "type": "integer"
      },
      "query": {
        "description": "Product name, e.g. 'Sony WH-1000XM5', 'iPhone 16 128GB'",
        "maxLength": 120,
        "minLength": 2,
        "type": "string"
      }
    },
    "required": [
      "query"
    ],
    "type": "object"
  },
  "provenance": {
    "method": "browser-inspect",
    "notes": "spikes/idealo.md plus a C4 in-page replay on 2026-11-07 (suggest 200 JSON, product page 200, 20 rows; first ld+json is the Product with AggregateOffer). Akamai blocks curl by client fingerprint (403 even with a Chrome UA); in-browser fetch works without special headers. Offer rows use classic BEM classes (productOffers-*). Never follow /relocator/relocate links: those are tracked click-outs to shops.",
    "recorded_at": "2026-11-07T12:45:00+01:00",
    "recorded_by": "C4"
  },
  "requires_login": false,
  "schema": "https://wield.run/schema/recipe/v1.json",
  "site": {
    "country": "DE",
    "id": "idealo.de",
    "language": "de",
    "name": "idealo",
    "origin": "https://www.idealo.de",
    "origins": [
      "https://www.idealo.de"
    ]
  },
  "steps": [
    {
      "description": "Query to idealo product id (first /OffersOfProduct/ suggestion).",
      "expect": {
        "assert": "length(body.groups[].items[] | [?contains(url, '/OffersOfProduct/')]) > `0`",
        "content_type": "json",
        "status": [
          200
        ]
      },
      "extract": {
        "json": {
          "category": "groups[].items[] | [?contains(url, '/OffersOfProduct/')] | [0].location",
          "name": "groups[].items[] | [?contains(url, '/OffersOfProduct/')] | [0].titlePlain",
          "product_id": "split(split(groups[].items[] | [?contains(url, '/OffersOfProduct/')] | [0].url, 'OffersOfProduct/')[1], '_')[0]",
          "url": "groups[].items[] | [?contains(url, '/OffersOfProduct/')] | [0].url"
        }
      },
      "id": "suggest",
      "request": {
        "headers": {
          "Accept": "application/json"
        },
        "method": "GET",
        "query": {
          "max": "10",
          "q": "{{params.query}}"
        },
        "url": "https://www.idealo.de/suggest"
      }
    },
    {
      "description": "Product page: JSON-LD aggregate offer and the first 20 offer rows.",
      "expect": {
        "content_type": "html",
        "status": [
          200
        ]
      },
      "extract": {
        "embedded_json": {
          "selector": "script[type=\"application/ld+json\"]",
          "vars": {
            "count": "offers.offerCount",
            "currency": "offers.priceCurrency",
            "high": "offers.highPrice",
            "low": "offers.lowPrice"
          }
        },
        "html_items": {
          "offers": {
            "fields": {
              "delivery": {
                "selector": ".productOffers-listItemOfferDeliveryStatus"
              },
              "price_text": {
                "selector": ".productOffers-listItemOfferPrice"
              },
              "shipping_text": {
                "selector": ".productOffers-listItemOfferShippingDetails"
              },
              "shop": {
                "attr": "data-shop-name",
                "selector": "[data-shop-name]"
              },
              "title": {
                "selector": ".productOffers-listItemTitleInner"
              }
            },
            "max": 20,
            "selector": "li.productOffers-listItem"
          }
        }
      },
      "id": "product",
      "parse": "html",
      "request": {
        "headers": {
          "Accept": "text/html"
        },
        "method": "GET",
        "url": "{{steps.suggest.url}}"
      }
    },
    {
      "delay_ms": 300,
      "description": "Offers 21-40 from the list fragment the 'Weitere Angebote' button loads.",
      "expect": {
        "content_type": "html",
        "status": [
          200
        ]
      },
      "extract": {
        "html_items": {
          "offers": {
            "fields": {
              "delivery": {
                "selector": ".productOffers-listItemOfferDeliveryStatus"
              },
              "price_text": {
                "selector": ".productOffers-listItemOfferPrice"
              },
              "shipping_text": {
                "selector": ".productOffers-listItemOfferShippingDetails"
              },
              "shop": {
                "attr": "data-shop-name",
                "selector": "[data-shop-name]"
              },
              "title": {
                "selector": ".productOffers-listItemTitleInner"
              }
            },
            "max": 20,
            "selector": "li.productOffers-listItem"
          }
        }
      },
      "id": "more",
      "parse": "html",
      "request": {
        "headers": {
          "Accept": "text/html"
        },
        "method": "GET",
        "query": {
          "excludeFilters": "0",
          "includeFilters": "0"
        },
        "url": "https://www.idealo.de/offerpage/offerlist/product/{{steps.suggest.product_id}}/start/20/sort/default"
      },
      "when": "params.max_offers == `40`"
    }
  ],
  "task": "Look up current shop prices for a product",
  "tos": {
    "notes": "idealo's terms prohibit automated extraction. One user-initiated lookup at a time from the user's own browser (2-3 requests). No click-outs to shops are triggered.",
    "reviewed": false
  },
  "verify": {
    "checks": [
      "length(output.offers) >= `10`",
      "contains(output.product, 'WH-1000XM5')",
      "output.lowest_price_eur > `50`",
      "output.offers[0].price_eur >= output.lowest_price_eur",
      "output.offers[0].total_with_shipping_eur >= output.offers[0].price_eur"
    ],
    "example_params": {
      "query": "Sony WH-1000XM5"
    },
    "max_ms": 5000
  },
  "version": 1
}