Scrapa eBay med Python: Kod som faktiskt fungerar

Senast uppdaterad April 16, 2026

De flesta guider om att scrapa eBay har ungefär tre månaders hållbarhet. Det vet jag, eftersom vårt team på Thunderbit har sett utvecklare fastna i trasiga kodsnuttar, gamla CSS-selektorer och ”fungerande” GitHub-repos som i tysthet slutade fungera för två eBay-omdesigner sedan.

eBay sitter på — den största datamängden för long-tail-prissättning på det öppna webben efter Amazon. Den datan driver allt från prisstrategi för återförsäljare till konkurrensanalys. Men att komma åt den programmatiskt är ett rörligt mål: eBays React-baserade frontend byter ut CSS-klassnamn, A/B-tester visar olika DOM-strukturer för olika användare, och Akamai Bot Manager står mellan dig och HTML-koden. Den här guiden ger dig Python-kod som fungerar idag, förklarar varför scrapers går sönder så att du kan bygga robustare lösningar, går ärligt igenom beslutet eBay API vs. scraping, och visar en no-code-lösning när Python inte är värt uppstarten.

Vad betyder det att scrapa eBay med Python?

Att webbscrapa eBay med Python innebär att skriva skript som programmatiskt laddar ner eBays webbsidor, tolkar HTML-koden (eller dold JSON) och plockar ut strukturerad data — titlar, priser, säljarinfo, försäljningsdatum, variantdetaljer — till ett format du faktiskt kan använda, som CSV, kalkylblad eller databas.

Du kan scrapa flera typer av eBay-sidor:

  • Sökresultat (t.ex. alla annonser för ”AirPods Pro”)
  • Enskilda produktsidor (fulla specifikationer, bilder, säljarinfo)
  • Sålda/slutförda annonser (faktiska transaktionspriser och datum)
  • Säljarprofiler och omdömen

Python är det självklara valet för det här arbetet. Ekosystemet — Requests, BeautifulSoup, lxml, pandas — gör det enkelt att hämta sidor, tolka HTML och bearbeta data. Det är dock skillnad på att scrapa webbplatsens HTML och att använda eBays officiella API — det tar vi upp härnäst.

Varför scrapa eBay? Verkliga användningsfall för affärsteam

Om du läser det här har du förmodligen redan ett syfte. Men det är ändå värt att förankra diskussionen i konkret affärsnytta, eftersom ROI:n från eBay-data verkligen är stark. Bain fann att en över tusentals företag. McKinsey tillskriver till dynamisk prissättning inom retail.

De vanligaste användningsfallen jag ser:

AnvändningsfallData som behövsAffärseffekt
Prisbevakning & omprissättningAktiva annonspriser, frakt, skickKonkurrenskraftig prissättning, skyddad marginal
KonkurrentanalysProduktsortiment, kampanjer, fraktvillkorStrategisk positionering, identifiering av sortimentsluckor
Marknadsanalys & trendspaningAnnonsvolym, kategoritrender, efterfrågemönsterIdentifiering av nya produkter, prognoser för efterfrågan
Prisbedömning för återförsäljareSålda priser, försäljningsdatum, skickRätt marknadsvärde, köp-/budbeslut
SentimentanalysRecensioner, betyg, returpolicyInsikter om produktkvalitet, kundnöjdhet
LeadgenereringSäljarprofiler, butiksinfo, kontaktuppgifterB2B-uppsök mot säljare med hög omsättning

ebayscraping_stats_77c7da1611.png

Det gemensamma temat: eBay har datan, men den är låst i webbsidor.

Scraping är hur du förvandlar den till en konkurrensfördel.

eBays officiella API vs. Python-webbscraping: Vad ska du välja?

Det här är frågan jag önskar att fler guider svarade ärligt på. eBay erbjuder officiella API:er — främst — och många undrar om de ska använda dem eller scrapa direkt. Svaret beror helt på vilken data du behöver.

KriteriumeBays Browse/Finding APIPython-webbscraping
Sålda/slutförda annonserBegränsat — Marketplace Insights API finns, men åtkomst avslås oftaFull åtkomst via URL-parametrar LH_Sold=1&LH_Complete=1
Hastighetsgränser5 000 anrop/dag på basnivånHanteras själv (beroende på proxy)
DatafältFördefinierade (titel, pris, kategori, grundläggande säljarinfo)Allt som syns på sidan (recensioner, fullständiga specifikationer, variantmatris)
UppstartskomplexitetOAuth 2.0, appregistrering, API-nycklarpip install + kod
StabilitetStabila endpointsGår sönder när HTML ändras
KostnadGratisnivå finns, betalt för större volymerGratis kod, men proxykostnader i skala
Variant-/MSKU-dataDelvis — ofta bara huvud-SKUFullt stöd (via parsing av dold JSON)
Sidnumreringens djupHårdtak på 10 000 artiklarI teorin obegränsat

En snabb notis: det gamla Finding API:t (som hade findCompletedItems) . Om du använder ebaysdk-python eller något bibliotek som träffar Finding-modulen, så är det trasigt i produktion just nu.

Min rekommendation: Använd Browse API för stabila, måttliga och strukturerade katalogfrågor på aktiva annonser. Använd Python-scraping när du behöver sålda priser, recensioner, variantdata eller något fält som API:t inte exponerar. Många team använder båda.

Verktyg och bibliotek du behöver för att scrapa eBay med Python

Innan vi skriver kod, här är verktygslådan. Du behöver ingen headless browser för de flesta eBay-sidor — datan ligger inbäddad i den serverrenderade HTML-koden.

BibliotekSyfte
requests eller httpxHTTP-klient för att ladda ner eBays sidor
curl_cffiHTTP-klient med riktig TLS-fingerprinting från webbläsare (avgörande för att kringgå Akamai)
beautifulsoup4HTML-parser för extrahering via CSS-selektorer
lxmlSnabb parser-backend för BeautifulSoup
jmespathFrågespråk för att tolka nästlad JSON
pandasDatabearbetning och export till CSV/Excel
gspreadIntegration med Google Sheets

Installera allt med ett enda kommando:

1pip install requests httpx curl_cffi beautifulsoup4 lxml jmespath pandas gspread

Använd Python 3.11+ — pandas 3.0 kräver 3.10+, och 3.11 ger 10–60 % snabbare prestanda i I/O-tunga arbetsflöden.

Ett bibliotek förtjänar särskild uppmärksamhet: curl_cffi är den enskilt största förbättringen en eBay-scraper kan få 2026. eBay använder , och Akamais främsta sätt att upptäcka bottar är TLS-fingerprinting. Vanliga requests skickar en Python-lik JA3-fingerprint som flaggas direkt. curl_cffi imiterar en riktig Chrome-webbläsares TLS-handshake, vilket klarar ungefär 90 % av Akamai-skyddade mål utan att du behöver en headless browser.

Steg för steg: Så scrapar du eBay-sökresultat med Python

Det här är kärnguiden. Vi ska scrapa eBays sökresultatsidor för produktannonser.

  • Svårighetsgrad: Nybörjare–Medel
  • Tidsåtgång: Cirka 30 minuter för första fungerande scrape
  • Det du behöver: Python 3.11+, biblioteken ovan, en terminal och en eBay-sök-URL

Steg 1: Skapa ditt Python-projekt

Skapa en projektmapp och installera beroenden:

1mkdir ebay-scraper && cd ebay-scraper
2python -m venv venv
3source venv/bin/activate  # Windows: venv\Scripts\activate
4pip install requests curl_cffi beautifulsoup4 lxml pandas

Skapa en fil som heter scrape_ebay.py. Det är din arbetsyta.

Steg 2: Bygg eBays sök-URL

eBays sök-URL-struktur är enkel. Den viktigaste parametern är _nkw (keyword):

1import urllib.parse
2keyword = "airpods pro"
3base_url = "https://www.ebay.com/sch/i.html"
4params = {
5    "_nkw": keyword,
6    "_ipg": "120",    # antal objekt per sida: 60, 120 eller 240 (240 kan trigga bot-flaggor)
7    "_pgn": "1",      # sidnummer
8}
9url = f"\{base_url\}?{urllib.parse.urlencode(params)}"
10print(url)
11# https://www.ebay.com/sch/i.html?_nkw=airpods+pro&_ipg=120&_pgn=1

Andra användbara parametrar:

  • LH_BIN=1 — endast Köp nu
  • _sacat=175673 — specifik kategori
  • _sop=12 — sortera efter bästa träff (10 = lägsta pris + frakt, 13 = nyligen upplagd)
  • LH_Complete=1&LH_Sold=1 — sålda/slutförda annonser (tas upp i ett särskilt avsnitt längre ner)

Steg 3: Skicka en förfrågan och hantera svaret

Det är här curl_cffi gör sitt jobb. En vanlig requests.get() ger ofta 403 från Akamai. Med curl_cffi låtsas vi vara en riktig Chrome-webbläsare:

1from curl_cffi import requests as cffi_requests
2import random, time
3USER_AGENTS = [
4    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36",
5    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36",
6    "Mozilla/5.0 (X11; Linux x86_64; rv:124.0) Gecko/20100101 Firefox/124.0",
7]
8HEADERS = {
9    "User-Agent": random.choice(USER_AGENTS),
10    "Accept-Language": "en-US,en;q=0.9",
11    "Accept-Encoding": "gzip, deflate, br",
12}
13def fetch_page(url, max_retries=5):
14    delay = 2
15    for attempt in range(max_retries):
16        try:
17            r = cffi_requests.get(url, impersonate="chrome124", headers=HEADERS, timeout=30)
18            if r.status_code == 200:
19                return r.text
20            if r.status_code in (403, 429, 503):
21                retry_after = r.headers.get("Retry-After")
22                sleep_for = float(retry_after) if retry_after else delay + random.uniform(0, 1)
23                print(f"  Status \{r.status_code\}, försöker igen om {sleep_for:.1f}s...")
24                time.sleep(sleep_for)
25                delay *= 2
26                continue
27            r.raise_for_status()
28        except Exception as e:
29            print(f"  Begäran misslyckades: \{e\}, försöker igen...")
30            time.sleep(delay)
31            delay *= 2
32    raise RuntimeError(f"Misslyckades efter \{max_retries\} försök: \{url\}")

Exponentiell backoff med jitter är viktig — fasta väntetider är i sig en bot-signatur.

Steg 4: Tolka produktannonserna från söksidan

eBay är just nu mitt i en migrering mellan två olika sökresultatslayouter. En robust scraper måste hantera båda:

FältGammal layoutNy layout
Kortcontainerli.s-itemli.s-card eller div.su-card-container
Titel.s-item__title.s-card__title
URLa.s-item__link[href]a.su-link[href]
Prisspan.s-item__price.s-card__price

Här är kod som klarar båda layouterna:

1from bs4 import BeautifulSoup
2def parse_search_results(html):
3    soup = BeautifulSoup(html, "lxml")
4    cards = soup.select("li.s-item, li.s-card, div.su-card-container")
5    results = []
6    for card in cards:
7        # Titel — prova båda layouterna
8        title_el = card.select_one(".s-item__title, .s-card__title")
9        title = title_el.get_text(strip=True) if title_el else None
10        # Hoppa över den tomma platshållarkortet "Shop on eBay"
11        if not title or "Shop on eBay" in title:
12            continue
13        # Pris
14        price_el = card.select_one("span.s-item__price, .s-card__price")
15        price = price_el.get_text(strip=True) if price_el else None
16        # URL
17        link_el = card.select_one("a.s-item__link[href], a.su-link[href]")
18        url = link_el["href"].split("?")[0] if link_el else None
19        # Bild
20        img_el = card.select_one("img.s-item__image-img, .s-card__image img")
21        image = None
22        if img_el:
23            image = img_el.get("src") or img_el.get("data-src")
24        # Frakt
25        ship_el = card.select_one("span.s-item__shipping, span.s-item__logisticsCost, .s-card__attribute-row")
26        shipping = ship_el.get_text(strip=True) if ship_el else None
27        results.append({
28            "title": title,
29            "price": price,
30            "url": url,
31            "image": image,
32            "shipping": shipping,
33        })
34    return results

Den där falska första kort-fällan är en klassisk miss. Det första li.s-item på många eBay-sökningar är en dold platshållare med titeln ”Shop on eBay” och inget riktigt pris. Filtrera alltid bort den.

Steg 5: Hantera sidnumrering för att scrapa flera sidor

eBay använder _pgn för sidnumrering. Länken till nästa sida använder a.pagination__next:

1import urllib.parse
2def scrape_ebay_search(keyword, max_pages=5):
3    all_results = []
4    for page_num in range(1, max_pages + 1):
5        params = {"_nkw": keyword, "_ipg": "120", "_pgn": str(page_num)}
6        url = f"https://www.ebay.com/sch/i.html?{urllib.parse.urlencode(params)}"
7        print(f"Scrapar sida \{page_num\}: \{url\}")
8        html = fetch_page(url)
9        results = parse_search_results(html)
10        if not results:
11            print(f"  Inga resultat på sida \{page_num\}, stoppar.")
12            break
13        all_results.extend(results)
14        print(f"  Hittade {len(results)} annonser (totalt: {len(all_results)})")
15        # Hänsynsfull paus — 3 till 8 sekunder med slump
16        time.sleep(random.uniform(3, 8))
17    return all_results

Den slumpmässiga pausen på 3–8 sekunder är inte valfri.

eBays Akamai-lager flaggar ihållande trafik över 1 begäran/sekund från en enda IP.

Steg 6: Exportera din data till CSV eller JSON

1import pandas as pd
2results = scrape_ebay_search("airpods pro", max_pages=3)
3df = pd.DataFrame(results)
4df.to_csv("ebay_airpods.csv", index=False)
5df.to_json("ebay_airpods.json", orient="records", indent=2)
6print(f"Exporterade {len(df)} annonser till CSV och JSON.")

Nu bör du ha ett rent kalkylblad med eBay-annonser. På min dator tog det cirka 45 sekunder att scrapa 3 sidor (360 annonser), inklusive pauser.

Så scrapar du eBays produktsidor med Python

Sökresultat ger dig en sammanfattning. Produktsidorna innehåller det viktiga: fullständiga beskrivningar, säljarens feedbackpoäng, objektspecifikationer, bildkaruseller och variantdata.

Tolka en enskild produktsida

eBays objektsidor ligger på /itm/<ITEM_ID>. Den mest stabila extraktionsvägen är JSON-LD — eBay bäddar in ett Product-schema som överlever nästan alla CSS-ändringar:

1import json
2def parse_item_page(html):
3    soup = BeautifulSoup(html, "lxml")
4    item = {}
5    # 1. JSON-LD — den mest stabila extraktionsvägen
6    for tag in soup.find_all("script", type="application/ld+json"):
7        try:
8            data = json.loads(tag.string or "")
9        except (json.JSONDecodeError, TypeError):
10            continue
11        if isinstance(data, dict) and data.get("@type") == "Product":
12            item["title"] = data.get("name")
13            item["brand"] = (data.get("brand") or {}).get("name")
14            item["images"] = data.get("image")
15            offers = data.get("offers") or {}
16            item["price"] = offers.get("price")
17            item["currency"] = offers.get("priceCurrency")
18            break
19    # 2. CSS-fallbacks för fält som inte finns i JSON-LD
20    def first_text(selectors):
21        for sel in selectors:
22            el = soup.select_one(sel)
23            if el and el.get_text(strip=True):
24                return el.get_text(strip=True)
25        return None
26    item.setdefault("title", first_text([
27        "h1.x-item-title__mainTitle",
28        "h1.x-item-title__mainTitle .ux-textspans--BOLD",
29    ]))
30    item["condition"] = first_text([
31        ".x-item-condition-text .ux-textspans",
32    ])
33    item["seller"] = first_text([
34        ".x-sellercard-atf__info__about-seller a .ux-textspans",
35    ])
36    item["shipping"] = first_text([
37        "div.ux-labels-values--shipping .ux-textspans--BOLD",
38    ])
39    # 3. Objektspecifikationer
40    specifics = {}
41    for dl in soup.select(".ux-layout-section-evo__item--table-view dl.ux-labels-values"):
42        k = dl.select_one(".ux-labels-values__labels-content .ux-textspans")
43        v = dl.select_one(".ux-labels-values__values-content .ux-textspans")
44        if k and v:
45            specifics[k.get_text(strip=True).rstrip(":")] = v.get_text(strip=True)
46    item["specifics"] = specifics
47    return item

Mönstret här — JSON-LD först, CSS-fallbacks sedan — är nyckeln till att bygga scrapers som inte går sönder varje kvartal. Mer om det längre ner.

Scrapa eBays produktvarianter (MSKU-data)

Vissa eBay-annonser har flera varianter — olika färger, storlekar eller lagringskapacitet. Den synliga DOM:en visar bara ett prisintervall som ”899 till 1 099 dollar” tills användaren klickar på ett alternativ. Det faktiska priset per variant ligger i ett dolt JavaScript-objekt som kallas MSKU.

Det här är ett område där eBays API bara ger delvis data (parent SKU), vilket gör scraping till det bättre alternativet.

1import re, json
2def extract_variants(html):
3    # Icke-girig matchning är avgörande — girig .+ slukar hela sidan
4    m = re.search(r'"MSKU"\s*:\s*(\{.+?\})\s*,\s*"QUANTITY"', html, re.DOTALL)
5    if not m:
6        return []
7    try:
8        msku = json.loads(m.group(1))
9    except json.JSONDecodeError:
10        return []
11    item_labels = {str(k): v["displayLabel"] for k, v in msku.get("menuItemMap", {}).items()}
12    skus = []
13    for combo_key, variation_id in msku.get("variationCombinations", {}).items():
14        option_ids = combo_key.split("_")
15        options = [item_labels.get(oid, oid) for oid in option_ids]
16        var = msku.get("variationsMap", {}).get(str(variation_id), {})
17        bin_model = var.get("binModel", {})
18        price_spans = bin_model.get("price", {}).get("textSpans", [{}])
19        price = price_spans[0].get("text") if price_spans else None
20        qty = var.get("quantity")
21        skus.append({
22            "options": options,
23            "price": price,
24            "quantity_available": qty,
25            "variation_id": variation_id,
26        })
27    return skus

Den där icke-giriga (.+?) i regexen är där varje eBay-scraper brukar falla. Girig .+ sväljer allt fram till sista "QUANTITY" på sidan, vilket ger trasig JSON. Jag har sett det här felet i minst tre ”fungerande” guider.

Så scrapar du eBays sålda och slutförda annonser med Python

Det här är användningsfallet som motiverar scraping framför API:t. Data om sålda varor — vad som faktiskt såldes, till vilket pris och på vilket datum — är guldstandarden för marknadsanalys, prisbedömning och återförsäljarstrategi. eBays Browse API ger uttryckligen inte detta. gör det tekniskt sett, men åtkomsten är en ”Limited Release” som .

De URL-parametrar du behöver är LH_Complete=1 (slutförda annonser) och LH_Sold=1 (begränsa till faktiskt sålda). Du måste ange båda. Bara LH_Sold=1 faller i vissa kategorier tyst tillbaka till aktiva annonser — det här är den vanligaste fallgropen i communityn.

1def scrape_sold_listings(keyword, max_pages=3):
2    all_sold = []
3    for page_num in range(1, max_pages + 1):
4        params = {
5            "_nkw": keyword,
6            "_ipg": "120",
7            "_pgn": str(page_num),
8            "LH_Complete": "1",
9            "LH_Sold": "1",
10        }
11        url = f"https://www.ebay.com/sch/i.html?{urllib.parse.urlencode(params)}"
12        print(f"Scrapar såld sida \{page_num\}...")
13        html = fetch_page(url)
14        soup = BeautifulSoup(html, "lxml")
15        cards = soup.select("li.s-item")
16        for card in cards:
17            title_el = card.select_one(".s-item__title")
18            title = title_el.get_text(strip=True) if title_el else None
19            if not title or "Shop on eBay" in title:
20                continue
21            # Inkludera bara faktiskt sålda objekt (grön POSITIVE-markering)
22            sold_tag = card.select_one(
23                ".s-item__title--tag .POSITIVE, .s-item__caption--signal.POSITIVE"
24            )
25            if sold_tag is None:
26                continue  # Slutförd men osåld annons — hoppa över
27            price_el = card.select_one("span.s-item__price")
28            price = price_el.get_text(strip=True) if price_el else None
29            # Tolka försäljningsdatum
30            sold_date = None
31            import re, datetime as dt
32            card_text = card.get_text()
33            m = re.search(r"Sold\s+([A-Z][a-z]\{2\}\s+\d{1,2},\s*\d\{4\})", card_text)
34            if m:
35                sold_date = dt.datetime.strptime(m.group(1), "%b %d, %Y").strftime("%Y-%m-%d")
36            link_el = card.select_one("a.s-item__link[href]")
37            url = link_el["href"].split("?")[0] if link_el else None
38            all_sold.append({
39                "title": title,
40                "sold_price": price,
41                "sold_date": sold_date,
42                "url": url,
43            })
44        if not cards:
45            break
46        time.sleep(random.uniform(3, 8))
47    return all_sold

Den viktiga skillnaden i HTML: sålda objekt visar priset i grönt (inne i en .POSITIVE-wrapper), medan osålda slutförda annonser visar priset i rött med överstrykning. Filtrera alltid på .POSITIVE-klassen.

Varför eBay-scrapers går sönder (och hur du bygger robusta sådana)

Om din eBay-scraper slutade fungera är du i gott sällskap. Det här är problem nummer ett i varje eBay-scrapingtråd jag har läst. Frågan är inte om din scraper går sönder — utan när.

Varför det händer:

  • eBay använder React-baserad rendering med dynamiskt genererade klassnamn som ändras vid deployment
  • A/B-tester serverar olika DOM-strukturer till olika användare (den dubbla s-item / s-card-layouten är ett levande exempel just nu)
  • Periodiska omdesigns ändrar HTML-strukturen även när datan är densamma
  • Gamla selektorer som #itemTitle och #prcIsum togs bort för flera år sedan men dyker fortfarande upp i guider

Som uttrycker det: ”Den verkliga utmaningen med eBay-webbscraping är att hantera eBays ändringar i CSS-selektorer. eBay uppdaterar sin frontend regelbundet, vilket bryter scrapers som förlitar sig på specifika klassnamn.”

ebayscraping_section_50be5cc410.png

Strategier för långlivade eBay-scrapers

Fyra strategier som överlever eBays kvartalsvisa ommöbleringar:

1. Prioritera JSON-LD framför CSS-selektorer. eBay bäddar in strukturerad Product-schema-data på varje objektsida. Datalagret förändras mycket mindre än presentationslagret — designers refaktorerar CSS-klasser varje kvartal, men backendfält som price, name och seller mappas till interna API:er och byter sällan namn.

2. Använd flera fallback-selektorer. Lita aldrig på bara en CSS-selektor. Ha alltid alternativ:

1def first_text(soup, selectors):
2    for sel in selectors:
3        el = soup.select_one(sel)
4        if el and el.get_text(strip=True):
5            return el.get_text(strip=True)
6    return None
7title = first_text(soup, [
8    "h1.x-item-title__mainTitle",
9    "h1.x-item-title__mainTitle .ux-textspans--BOLD",
10    "[data-testid='x-item-title'] h1",
11])

3. Tolka dolda JSON-block. MSKU-objektet för varianter och inbäddad JavaScript-data överlever CSS-ändringar eftersom de genereras på serversidan. Regex-extraktion från <script>-taggar kräver mer arbete i början men minskar underhållet kraftigt.

4. Logga när selektorer misslyckas. Lägg in övervakning så att du vet när en selektor slutar matcha, inte bara att datan blev tom:

1if title is None:
2    print(f"VARNING: titel-selektorn misslyckades för \{url\}")

5. Använd curl_cffi med webbläsarimpersonation. Det hanterar Akamais TLS-fingerprinting utan att du behöver en headless browser.

AI-drivet alternativ: inget selektorunderhåll

Om du tröttnat på att lappa selektorer varannan månad finns det ett fundamentalt annat angreppssätt. Verktyg som använder AI för att läsa sidan på nytt varje gång och härleda extraktionslogiken dynamiskt. En studie från McGill University testade AI mot selektorbaserade scrapers över 3 000 sidor och fann att , med branschjämförelser som pekar på .

MetodGår sönder när eBay ändrar HTML?Underhållsarbete
Hårdkodade CSS-selektorerJa, varje kvartalHögt — löpande patchning
Dold JSON / JSON-LD-extraktionSällanLågt
AI-baserad scraping (Thunderbit)Nej — AI:n härleder selektorer varje körningInget

Jag går igenom Thunderbit-flödet mer detaljerat längre fram. För stunden: om du bygger en scraper som ska köras i månader bör du satsa på JSON-först-extraktion och fallback-selektorer. Om du inte vill underhålla selektorer alls är AI-vägen väl värd att titta på.

Automatisera återkommande eBay-scrapes för prisbevakning

En engångsscrape är användbar. Men prisbevakning, lageruppföljning och konkurrentanalys kräver återkommande datainsamling. Varje konkurrentartikel jag har läst nämner prisbevakning som ett användningsfall, men nästan ingen visar hur man faktiskt automatiserar det.

Alternativ 1: Cron-jobb (Linux/macOS) eller Aktivitetsschemaläggaren (Windows)

Det enklaste sättet. Lägg ditt Python-skript i ett cron-jobb. Använd alltid den absoluta sökvägen till din venv:s Python — cron kör med en minimal miljö:

1crontab -e
2# Dagligen kl 08:15
315 8 * * * /Users/me/ebay/venv/bin/python /Users/me/ebay/scrape_ebay.py >> /Users/me/ebay/scrape.log 2>&1

På Windows använder du PowerShell:

1$A = New-ScheduledTaskAction -Execute "C:\Users\me\ebay\venv\Scripts\python.exe" -Argument "C:\Users\me\ebay\scrape_ebay.py"
2$T = New-ScheduledTaskTrigger -Daily -At 8:15am
3Register-ScheduledTask -TaskName "eBayScraper" -Action $A -Trigger $T

Det här kräver en dator som alltid är igång, och du hanterar proxies och anti-bot-skydd själv.

Alternativ 2: Cloud Functions (serverless)

AWS Lambda eller Google Cloud Functions låter dig köra scrapers utan en dedikerad server. Högre uppstartskrav — du måste paketera beroenden, hantera timeouts (Lambda stoppar vid 15 minuter) och fortfarande sköta proxies. Men ingen serverdrift.

Alternativ 3: No-code-schemaläggning med Thunderbit

funktion Scheduled Scraper låter dig beskriva intervallet med vanlig text (t.ex. ”varje dag kl. 8”), mata in eBay-URL:er och klicka på Schema. Den kör i molnet med inbyggt anti-bot-skydd.

MetodUppstartsstorlekBehöver server?Hantera anti-bot?
Cron + Python-skriptMedelJa (alltid på)Du sköter proxies
Cloud function (Lambda)HögNej (serverless)Du sköter proxies
Thunderbit Scheduled ScraperLåg (beskriv med ord)Nej (molnbaserat)Inbyggt

För att lagra återkommande scrape-data är en lokal SQLite-databas rätt val för prishistorik. Använd ON CONFLICT ... DO UPDATE (inte INSERT OR REPLACE, som ):

1CREATE TABLE IF NOT EXISTS listings (
2    item_id       TEXT PRIMARY KEY,
3    title         TEXT NOT NULL,
4    price         REAL,
5    last_price    REAL,
6    first_seen_at TEXT DEFAULT (datetime('now')),
7    last_seen_at  TEXT DEFAULT (datetime('now'))
8);
9CREATE TABLE IF NOT EXISTS price_history (
10    item_id     TEXT NOT NULL,
11    observed_at TEXT NOT NULL DEFAULT (datetime('now')),
12    price       REAL NOT NULL,
13    PRIMARY KEY (item_id, observed_at)
14);

Vill du inte koda? Så scrapar du eBay på 2 minuter med Thunderbit

Jag har ägnat 2 000 ord åt Python-kod. Nu vill jag vara ärlig med när du inte behöver den.

Om du är en affärsanvändare som gör engångsmarknadsresearch, en återförsäljare som jämför comps, eller ett ecommerce-team som behöver data idag utan ett utvecklingssprint, är Python överkurs. Uppstarten, underhållet av selektorer, proxyhanteringen — det är mycket overhead för ”jag behöver bara de här 200 annonserna i ett kalkylblad”.

Så scrapar Thunderbit eBay (steg för steg)

  1. Installera — inget kreditkort krävs.
  2. Öppna valfri eBay-sökresultatsida eller produktsida i Chrome.
  3. Klicka på ”AI Suggest Fields” i Thunderbit-sidopanelen. AI:n läser sidan och föreslår kolumner: Titel, Pris, Skick, Frakt, Säljare, Betyg.
  4. Klicka på ”Scrape.” Tillägget går igenom pagineringen och fyller datatabellen. För eBay finns dessutom som fungerar med ett klick.
  5. Exportera till Google Sheets, Airtable, Notion, CSV, JSON eller Excel — gratis.

Hela processen tar under 2 minuter.

Jag mätte det.

Berikning av undersidor: få data från detaljsidor utan extra kod

Efter att ha scrapat en sökresultatsida kan Thunderbit besöka varje annons detaljsida och lägga till fler fält — fullständiga specifikationer, säljarinfo, beskrivning, alla bilder. Det ersätter de 20+ rader Python-kod för att scrapa undersidor som vi skrev tidigare med ett enda klick.

När Python fortfarande är rätt val

Python vinner när du behöver:

  • Scraping i stor skala (tiotusentals sidor per körning)
  • Djupt anpassad parserlogik eller datatransformation
  • Integration i befintliga datapipelines (Airflow, dbt, Kafka)
  • Finmaskig kontroll över TLS/sessioner för avancerat anti-bot-arbete
  • Enhetskostnad — i miljontals rader vinner en underhållen stack över kreditbaserad SaaS

För de flesta engångs- eller mellanstora projekt är Thunderbit snabbare och enklare. För produktionspipelines i stor skala ger Python dig full kontroll.

Tips för att undvika att bli blockerad när du scrapar eBay med Python

eBays Akamai-lager är på riktigt. Det som faktiskt fungerar i praktiken:

  • Använd curl_cffi med impersonate="chrome124" — den största förbättringen jämfört med vanliga requests
  • Rotera User-Agent-strängar från en lista med aktuella webbläsarversioner (Chrome 143, Firefox 124, Safari 26)
  • Lägg in slumpmässiga fördröjningar — fasta intervaller är en fingerprint
  • Använd residential- eller roterande proxies för allt över några dussin sidor. Datacenter-IP:er (AWS, GCP, DigitalOcean) flaggas snabbt av Akamai.
  • Respektera robots.txt — de flesta filtrerade browse-URL:er är uttryckligen förbjudna; objektsidor (/itm/<id>) är det inte
  • Hantera CAPTCHA på ett smidigt sätt — upptäck dem och försök igen med en annan IP, eller använd en CAPTCHA-lösningstjänst
  • Belasta inte servern för hårt. Prejudikatet säger att trespass to chattels kan tillämpas när scraping faktiskt försämrar servrar. Håller du dig runt 1 begäran/sekund per IP ligger du långt under den gränsen.

För kommersiell användning i hög volym: överväg att använda Browse API för aktiva annonser och bara scrapa riktat för sålda comps och data som API:t inte exponerar. Den hybriden är renare både tekniskt och juridiskt.

Är det lagligt att scrapa eBay med Python?

Jag är inte jurist, och det här blogginlägget är inte juridisk rådgivning. Så jag håller det kort.

Den juridiska utvecklingen har rört sig i riktning mot scraping av offentligt tillgänglig data. De viktigaste prejudikaten:

  • (9:e kretsen, 2022): scraping av offentligt tillgänglig data bryter inte mot CFAA
  • Van Buren v. United States (US Supreme Court, 2021): snävade in CFAA:s ”exceeds authorized access”-bestämmelse
  • (N.D. Cal., 2024): scraping utloggat bryter inte mot plattformens användarvillkor eftersom scrapen inte är en ”användare”

Med det sagt förbjuder eBays uttryckligen ”buy-for-me-agents, LLM-drivna bottar eller något end-to-end-flöde som försöker lägga beställningar utan mänsklig granskning.” Gränsen är tydlig: read-only-scraping av offentliga sidor står starkt; att automatisera checkout gör det inte.

Bästa praxis: scrapa bara offentligt synlig data. Skapa inte fejkade konton och kringgå inte inloggningsväggar. Återförsälj inte upphovsrättsskyddade annonsbilder i bulk. Och rådfråga jurist vid kommersiella projekt i större skala.

Slutsats och viktigaste lärdomar

Python är det mest flexibla sättet att scrapa eBay, men det kräver löpande underhåll när webbplatsens HTML ändras. Beslutsramen är:

  • Använd eBays Browse API för stabila, måttliga och strukturerade frågor om aktiva annonser
  • Använd Python-scraping för sålda annonser, recensioner, variantdata och allt API:t inte exponerar
  • Använd om du vill ha eBay-data utan att skriva eller underhålla kod

Koden i den här guiden prioriterar robusthet: JSON-LD först, flera CSS-fallbacks sedan, dold JSON-parsing för varianter. Det lager-på-lager-upplägget gör att din scraper inte dör nästa gång eBays frontend-team släpper en omdesign.

Om du vill testa no-code-vägen kan låta dig prova direkt på eBay-sidor. Och om du vill se hur fungerar är det bara ett klick bort.

För mer om verktyg för webbscraping, kolla in våra guider om , och . Du kan också se tutorials på .

Testa Thunderbit för eBay-scraping

Vanliga frågor

1. Kan jag scrapa eBay gratis med Python?

Ja. Alla bibliotek (Requests, BeautifulSoup, curl_cffi, pandas) är gratis och öppen källkod. Kostnaderna kommer i skala — residential proxies för scraping i hög volym kostar normalt 50–500 USD/månad beroende på bandbredd. För små projekt (några hundra sidor) kan du scrapa från din hem-IP med försiktig rate limiting.

2. Hur scrapar jag eBays sålda objekt och slutförda annonser med Python?

Lägg till LH_Complete=1&LH_Sold=1 i sök-URL:ens parametrar. Du måste ange båda — LH_Sold=1 ensam faller i vissa kategorier tyst tillbaka till aktiva annonser. Filtrera resultaten genom att kontrollera .POSITIVE-klassen på pris-elementet, vilket visar att det faktiskt är en försäljning och inte en osåld utgången annons.

3. Blockerar eBay webbscraping?

eBay använder Akamai Bot Manager, som främst upptäcker scrapers genom TLS-fingerprinting och beteendeanalys. Vanliga requests-anrop får ofta 403-svar. Med curl_cffi och webbläsarimpersonation, roterande User-Agents och 3–8 sekunders slumpmässiga pauser mellan begärningar klarar du de flesta blockeringar. Residential proxies hjälper i större skala.

4. Ska jag använda eBays API eller webbscraping?

Använd Browse API för stabila frågor i måttlig volym om aktiva annonser (upp till 5 000 anrop/dag). Använd scraping när du behöver historik över sålda priser, fullständig variant-/MSKU-data, recensioner eller något fält som API:t inte exponerar. Marketplace Insights API ger tekniskt sett såld data, men åtkomsten är begränsad och .

5. Vad är det enklaste sättet att scrapa eBay utan kod?

använder AI för att läsa eBay-sidor, föreslå datakolumner och extrahera annonser med ett klick. Den hanterar paginering, berikning av undersidor och export till Google Sheets, Excel, Airtable eller Notion. Färdiga gör det ännu snabbare för vanliga behov.

Läs mer

Innehållsförteckning

Testa Thunderbit

Skrapa leads och annan data på bara 2 klick. Drivet av AI.

Skaffa Thunderbit Det är gratis
Extrahera data med AI
Överför enkelt data till Google Sheets, Airtable eller Notion
Chrome Store Rating
PRODUCT HUNT#1 Product of the Week