> ## Documentation Index
> Fetch the complete documentation index at: https://docs.olostep.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Scrape

> Verwandle jede URL in LLM-bereites Markdown, HTML, Screenshots, PDFs oder strukturiertes JSON.

Über den Olostep `/v1/scrapes` Endpunkt kannst du LLM-freundliches Markdown, HTML, Text, Screenshots oder strukturiertes JSON in Echtzeit aus jeder URL extrahieren.

* Gibt sauberes Markdown, strukturierte Daten, Screenshots oder HTML aus
* Extrahiere JSON über [Parsers](/features/structured-content/parsers) oder [LLM-Extraktion](/features/structured-content/llm-extraction)
* Handhabt dynamische Inhalte: JS-gerenderte Seiten, Anmeldeabläufe über Aktionen, PDFs

Für API-Details siehe die [Scrape-Endpunkt-API-Referenz](/api-reference/scrapes/create).

## Eine URL scrapen

Verwende den `/v1/scrapes` Endpunkt, um eine einzelne URL zu scrapen und Ausgabeformate auszuwählen.

### Installation

<CodeGroup>
  ```python Python theme={null}
  pip install olostep
  ```

  ```javascript Node theme={null}
  npm install olostep
  ```

  ```bash cURL theme={null}
  # curl ist standardmäßig auf macOS, Linux und Windows verfügbar
  ```

  ```javascript Node (API) theme={null}
  npm install node-fetch
  ```

  ```bash Python (API) theme={null}
  pip install requests
  ```
</CodeGroup>

### Verwendung

Du kannst den Endpunkt verwenden, um eine einzelne URL zu scrapen und Ausgabeformate auszuwählen. Die obligatorischen Parameter sind `url_to_scrape` und `formats`.

Einige andere häufige Parameter sind `wait_before_scraping` (in Millisekunden), `remove_css_selectors` (Standard, keine oder ein Array von Selektoren) und `country`.

<CodeGroup>
  ```python Python theme={null}
  from olostep import Olostep

  client = Olostep(api_key="YOUR_REAL_KEY")

  result = client.scrapes.create(
      url_to_scrape="https://en.wikipedia.org/wiki/Alexander_the_Great",
      formats=["markdown", "html"],
  )

  print(result.markdown_content)
  print(result.html_content)
  ```

  ```js Node theme={null}
  import Olostep from 'olostep'

  const client = new Olostep({ apiKey: 'YOUR_REAL_KEY' })

  const result = await client.scrapes.create({
    url: 'https://en.wikipedia.org/wiki/Alexander_the_Great',
    formats: ['markdown', 'html'],
  })

  console.log(result.markdown_content)
  console.log(result.html_content)
  ```

  ```bash cURL theme={null}
  curl -s -X POST "https://api.olostep.com/v1/scrapes" \
    -H "Authorization: Bearer $OLOSTEP_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "url_to_scrape": "https://en.wikipedia.org/wiki/Alexander_the_Great",
      "formats": ["markdown", "html"]
    }'
  ```

  ```bash CLI theme={null}
  olostep scrape "https://en.wikipedia.org/wiki/Alexander_the_Great" \
    --formats markdown,html
  ```

  ```js Node (API) theme={null}
  const endpoint = 'https://api.olostep.com/v1/scrapes'
  const payload = {
    url_to_scrape: 'https://en.wikipedia.org/wiki/Alexander_the_Great',
    formats: ['markdown', 'html']
  }
  const res = await fetch(endpoint, {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer <YOUR_API_KEY>',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify(payload)
  })
  const data = await res.json()
  console.log(data)
  ```

  ```python Python (API) theme={null}
  import requests
  import json

  endpoint = "https://api.olostep.com/v1/scrapes"
  payload = {
      "url_to_scrape": "https://en.wikipedia.org/wiki/Alexander_the_Great",
      "formats": ["markdown", "html"]
  }
  headers = {
      "Authorization": "Bearer <YOUR_API_KEY>",
      "Content-Type": "application/json"
  }

  response = requests.post(endpoint, json=payload, headers=headers)
  print(json.dumps(response.json(), indent=2))
  ```
</CodeGroup>

### Antwort

Die API gibt ein `scrape`-Objekt als Antwort zurück.

Das `scrape` hat einige Eigenschaften wie `id` und `result`.

Das `result`-Objekt hat die folgenden Felder (je nach `formats`-Parameter können einige null sein):

* `html_content`: der HTML-Inhalt der Seite. Gib `formats: ["html"]` an, um dies zu erhalten.
* `markdown_content`: der MD-Inhalt der Seite. Gib `formats: ["markdown"]` an, um dies zu erhalten.
* `text_content`: der Textinhalt der Seite. Gib `formats: ["text"]` an, um dies zu erhalten.
* `json_content`: der JSON-Inhalt der Seite. Gib `formats: ["json"]` an, um dies zu erhalten, und stelle auch einen `parser` oder `llm_extract`-Parameter bereit.
* `screenshot_hosted_url`: die gehostete URL des Screenshots.
* `html_hosted_url`: die gehostete URL des HTML-Inhalts
* `markdown_hosted_url`: die gehostete URL des Markdown-Inhalts
* `json_hosted_url`: die gehostete URL des JSON-Inhalts
* `text_hosted_url`: die gehostete URL des Textinhalts
* `links_on_page`: die Links auf der Seite
* `page_metadata`: die Metadaten der Seite

```json theme={null}
{
  "id": "scrape_6h89o8u1kt",
  "object": "scrape",
  "created": 1745673871,
  "metadata": {},
  "retrieve_id": "6h89o8u1kt",
  "url_to_scrape": "https://en.wikipedia.org/wiki/Alexander_the_Great",
  "result": {
    "html_content": "<html...",
    "markdown_content": "## Alexander the Great...",
    "text_content": null,
    "json_content": null,
    "screenshot_hosted_url": null,
    "html_hosted_url": "https://olostep-storage.s3.us-east-1.amazonaws.com/text_6h89o8u1kt.txt",
    "markdown_hosted_url": "https://olostep-storage.s3.us-east-1.amazonaws.com/markDown_6h89o8u1kt.txt",
    "json_hosted_url": null,
    "text_hosted_url": null,
    "links_on_page": [],
    "page_metadata": { "status_code": 200, "title": "" }
  }
}
```

## Caching

Um die Geschwindigkeit zu optimieren, bietet Olostep eine optionale gemeinsame Caching-Schicht für HTML-, Markdown-, Text- und geparste JSON-Ergebnisse.

### Wie es funktioniert

Wenn ein Scrape angefordert wird, überprüft Olostep, ob ein passendes Scrape mit denselben Parametern bereits existiert. Wenn ein ausreichend frisches Match gefunden wird, wird der Inhalt sofort aus Olosteps Speicher bereitgestellt, ohne einen neuen Browser-Scrape zu starten.

* **Gemeinsamer Cache:** Der Cache wird global geteilt. Wenn eine andere Anfrage dieselbe URL mit derselben Konfiguration innerhalb deines Frischefensters gescrapt hat, profitierst du von der Geschwindigkeitssteigerung.
* **Nachbearbeitung ist weiterhin live:** Operationen wie `llm_extract` und `links_on_page`-Filter werden *on-the-fly* auf dem zwischengespeicherten Dokument ausgeführt. Du cachest nur die Kernseitenabfrage und hältst deine strukturierten Extraktionen dynamisch.

### Frische und `max_age`

Standardmäßig führt die Produktions-API immer einen Live-Scrape durch, um Echtzeitgenauigkeit zu gewährleisten. Du kannst das Caching mit dem `max_age`-Parameter aktivieren.

| Parameter | Typ       | Standard | Beschreibung                                                                                                                                                          |
| --------- | --------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `max_age` | `integer` | `0`      | Akzeptables Inhaltsalter in **Sekunden**. Wenn eine zwischengespeicherte Kopie existiert und neuer als `max_age` Sekunden ist, wird sie aus dem Cache bereitgestellt. |

* **Standard-API-Verhalten (`max_age: 0`):** Jede API-Anfrage löst einen frischen Scrape aus.
* **Standard-Playground-Verhalten:** Im Dashboard-Playground ist `max_age` standardmäßig auf 24 Stunden (`86400` Sekunden) eingestellt, um redundante Scrapes zu verhindern und Credits zu sparen, während du entwickelst und testest.
* **Maximales Alter:** Der Cache hat ein hartes Limit von **7 Tagen** (`604800` Sekunden). Jede angeforderte `max_age` über diesem Limit fällt auf ein Maximum von 7 Tagen zurück.

### Anwendungsbeispiele

<CodeGroup>
  ```python Python theme={null}
  from olostep import Olostep

  client = Olostep(api_key="YOUR_REAL_KEY")

  # Opt-in zum Caching: Akzeptiere Ergebnisse bis zu 1 Tag (86400 Sekunden) alt
  result = client.scrapes.create(
      url_to_scrape="https://example.com",
      formats=["markdown"],
      max_age=86400
  )
  ```

  ```js Node theme={null}
  import Olostep from 'olostep'

  const client = new Olostep({ apiKey: 'YOUR_REAL_KEY' })

  // Opt-in zum Caching: Akzeptiere Ergebnisse bis zu 1 Tag (86400 Sekunden) alt
  const result = await client.scrapes.create({
    url: 'https://example.com',
    formats: ['markdown'],
    maxAge: 86400,
  })
  ```

  ```bash cURL theme={null}
  # Opt-in zum Caching: Akzeptiere Ergebnisse bis zu 1 Stunde (3600 Sekunden) alt
  curl -X POST "https://api.olostep.com/v1/scrapes" \
    -H "Authorization: Bearer $OLOSTEP_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "url_to_scrape": "https://example.com",
      "formats": ["markdown"],
      "max_age": 3600
    }'
  ```

  ```js Node (API) theme={null}
  const endpoint = 'https://api.olostep.com/v1/scrapes'
  const payload = {
    url_to_scrape: 'https://example.com',
    formats: ['markdown'],
    max_age: 86400 // Akzeptiere Ergebnisse bis zu 1 Tag (86400 Sekunden) alt
  }
  const res = await fetch(endpoint, {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer <YOUR_API_KEY>',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify(payload)
  })
  const data = await res.json()
  console.log(data)
  ```

  ```python Python (API) theme={null}
  import requests
  import json

  endpoint = "https://api.olostep.com/v1/scrapes"
  payload = {
      "url_to_scrape": "https://example.com",
      "formats": ["markdown"],
      "max_age": 86400 # Akzeptiere Ergebnisse bis zu 1 Tag (86400 Sekunden) alt
  }
  headers = {
      "Authorization": "Bearer <YOUR_API_KEY>",
      "Content-Type": "application/json"
  }

  response = requests.post(endpoint, json=payload, headers=headers)
  print(json.dumps(response.json(), indent=2))
  ```
</CodeGroup>

### Wann wird der Cache übersprungen?

Der Cache wird automatisch umgangen (was einen Live-Scrape erzwingt) für Funktionen, die einzigartige Sitzungen, Echtzeit-Visualisierungen oder benutzerdefinierte Dateiverarbeitung erfordern:

* **Interaktive Sitzungen:** Anfragen, die `session_id` verwenden oder einen benutzerdefinierten Browser `context` laden.
* **Visuals:** Visualisierungstools und Screenshots (`htmlVisualizer`).
* **Spezielle Dateitypen:** Binäre Dateidownloads oder rohe PDF-Darstellung.
* **Debugging & Netzwerk:** Erfassung von `network_calls` oder Verwendung asynchroner Parser-Jobs.

## Links extrahieren

Übergebe ein `links_on_page`-Objekt in der Anfrage, um die auf der Seite gefundenen Links zu sammeln. Alle Links werden als absolute URLs zurückgegeben.

```json theme={null}
"links_on_page": {
  "include_links": ["/blog/*"],
  "exclude_links": ["*.pdf"],
  "query_to_order_links_by": "pricing"
}
```

* `include_links` / `exclude_links`: Glob-Muster, die mit dem **Pfad** jeder Link-URL abgeglichen werden.
* `query_to_order_links_by`: sortiert die zurückgegebenen Links nach Relevanz zu diesem Text.

<Note>
  Glob-Muster passen auf Pfadsegmente. Ein einzelnes `*` überschreitet **nicht** `/`, daher passt `"/blog/*"` auf `"/blog/post-1"`, aber **nicht** auf den Index `"/blog"` selbst — und es passt nie auf `"/blog?tag=x"`, da Abfragezeichenfolgen nicht Teil des Pfads sind. Um auch den Index einzuschließen, verwende `"/blog*"` oder `"{/blog,/blog/**}"`.
</Note>

## Scrape-Formate

Wähle ein oder mehrere Ausgabeformate über `formats`:

* `markdown`: LLM-freundliches Markdown
* `html`: bereinigtes HTML
* `text`: Klartext
* `json`: strukturiertes Ausgabeformat (über Parser oder llm\_extract)
* `raw_pdf`: rohe PDF-Bytes, die zu einer gehosteten URL extrahiert werden
* `screenshot`: über Aktionen festgelegt, um einen Screenshot zu erfassen und eine gehostete URL zurückzugeben

Ausgabeschlüssel werden innerhalb von `result` als `*_content`-Felder und eine `*_hosted_url` zurückgegeben.

## Strukturierte Daten extrahieren

Du kannst strukturiertes JSON auf zwei Arten extrahieren: mit Parsers oder LLM-Extraktion.

### Verwendung eines Parsers (empfohlen für Skalierung)

Definiere `formats: ["json"]` und stelle eine Parser-`id` bereit.

<CodeGroup>
  ```python Python theme={null}
  from olostep import Olostep

  client = Olostep(api_key="YOUR_REAL_KEY")

  result = client.scrapes.create(
      url_to_scrape="https://www.google.com/search?q=alexander+the+great&gl=us&hl=en",
      formats=["json"],
      parser="@olostep/google-search",
  )

  print(result.json_content)
  ```

  ```js Node theme={null}
  import Olostep from 'olostep'

  const client = new Olostep({ apiKey: 'YOUR_REAL_KEY' })

  const result = await client.scrapes.create({
    url: 'https://www.google.com/search?q=alexander+the+great&gl=us&hl=en',
    formats: ['json'],
    parser: '@olostep/google-search',
  })

  console.log(result.json_content)
  ```

  ```bash cURL theme={null}
  curl -s -X POST "https://api.olostep.com/v1/scrapes" \
    -H "Authorization: Bearer $OLOSTEP_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "url_to_scrape": "https://www.google.com/search?q=alexander+the+great&gl=us&hl=en",
      "formats": ["json"],
      "parser": {"id": "@olostep/google-search"}
    }'
  ```

  ```bash CLI theme={null}
  olostep scrape "https://www.google.com/search?q=alexander+the+great&gl=us&hl=en" \
    --formats json \
    --payload-json '{"parser":{"id":"@olostep/google-search"}}'
  ```

  ```js Node (API) theme={null}
  const res = await fetch('https://api.olostep.com/v1/scrapes', {
    method: 'POST',
    headers: { 'Authorization': 'Bearer <YOUR_API_KEY>', 'Content-Type': 'application/json' },
    body: JSON.stringify({
      url_to_scrape: 'https://www.google.com/search?q=alexander+the+great&gl=us&hl=en',
      formats: ['json'],
      parser: { id: '@olostep/google-search' }
    })
  })
  console.log(await res.json())
  ```

  ```python Python (API) theme={null}
  import requests, json

  endpoint = "https://api.olostep.com/v1/scrapes"
  payload = {
    "url_to_scrape": "https://www.google.com/search?q=alexander+the+great&gl=us&hl=en",
    "formats": ["json"],
    "parser": { 
      "id": "@olostep/google-search" 
    }
  }
  headers = {
      "Authorization": "Bearer <YOUR_API_KEY>", 
      "Content-Type": "application/json"
  }

  res = requests.post(endpoint, json=payload, headers=headers)
  print(json.dumps(res.json(), indent=2))
  ```
</CodeGroup>

Olostep hat einige vorgefertigte Parser für [beliebte Websites](https://www.olostep.com/store), aber du kannst auch deine eigenen Parser über das Dashboard erstellen oder unser Team bitten, dies für dich zu tun.

Parser sind selbstheilend und aktualisieren sich selbst auf die neueste Version der Website.

### Verwendung der LLM-Extraktion (Schema und/oder Prompt)

Stelle `llm_extract` mit einem JSON-Schema (`schema`) und/oder einer natürlichen Sprachinstruktion (`prompt`) bereit. Du kannst beide Parameter übergeben, aber wenn beide bereitgestellt werden, hat `schema` Vorrang.

Wenn du stattdessen nur einen `prompt` übergibst, extrahiert das LLM die Daten basierend auf dem Prompt und entscheidet selbst über die Datenstruktur.

<CodeGroup>
  ```python Python theme={null}
  from olostep import LLMExtract, Olostep

  client = Olostep(api_key="YOUR_REAL_KEY")

  result = client.scrapes.create(
      url_to_scrape="https://www.berklee.edu/events/stefano-marchese-friends",
      formats=["markdown", "json"],
      llm_extract=LLMExtract(
          schema={
              "event": {
                  "type": "object",
                  "properties": {
                      "title": {"type": "string"},
                      "date": {"type": "string"},
                      "description": {"type": "string"},
                      "venue": {"type": "string"},
                      "address": {"type": "string"},
                      "start_time": {"type": "string"},
                  },
              }
          }
      ),
  )

  print(result.json_content)
  ```

  ```js Node theme={null}
  import Olostep from 'olostep'

  const client = new Olostep({ apiKey: 'YOUR_REAL_KEY' })

  const result = await client.scrapes.create({
    url: 'https://www.berklee.edu/events/stefano-marchese-friends',
    formats: ['markdown', 'json'],
    llmExtract: {
      schema: {
        event: {
          type: 'object',
          properties: {
            title: { type: 'string' },
            date: { type: 'string' },
            description: { type: 'string' },
            venue: { type: 'string' },
            address: { type: 'string' },
            start_time: { type: 'string' },
          },
        },
      },
    },
  })

  console.log(result.json_content)
  ```

  ```bash cURL theme={null}
  curl -s -X POST "https://api.olostep.com/v1/scrapes" \
    -H "Authorization: Bearer $OLOSTEP_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "url_to_scrape": "https://www.berklee.edu/events/stefano-marchese-friends",
      "formats": ["json"],
      "llm_extract": {
        "prompt": "Extract the event title, date, description, venue, address, and start time from the page."
      }
    }'
  ```

  ```bash CLI theme={null}
  olostep scrape "https://www.berklee.edu/events/stefano-marchese-friends" \
    --formats json \
    --payload-json '{"llm_extract":{"prompt":"Extract the event title, date, description, venue, address, and start time from the page."}}'
  ```

  ```js Node (API) theme={null}
  const res = await fetch('https://api.olostep.com/v1/scrapes', {
    method: 'POST',
    headers: { 'Authorization': 'Bearer <YOUR_API_KEY>', 'Content-Type': 'application/json' },
    body: JSON.stringify({
      url_to_scrape: 'https://www.berklee.edu/events/stefano-marchese-friends',
      formats: ['json'],
      llm_extract: {
        prompt: 'Extract the event title, date, description, venue, address, and start time from the page.'
      }
    })
  })
  console.log(await res.json())
  ```

  ```python Python (API) theme={null}
  import requests, json

  endpoint = "https://api.olostep.com/v1/scrapes"
  payload = {
    "url_to_scrape": "https://www.berklee.edu/events/stefano-marchese-friends",
    "formats": ["markdown", "json"],
    "llm_extract": {
      "schema": {
        "event": {
          "type": "object",
          "properties": {
            "title": {"type": "string"},
            "date": {"type": "string"},
            "description": {"type": "string"},
            "venue": {"type": "string"},
            "address": {"type": "string"},
            "start_time": {"type": "string"}
          }
        }
      }
    }
  }
  headers = {
      "Authorization": "Bearer <YOUR_API_KEY>",
      "Content-Type": "application/json"
  }
  res = requests.post(endpoint, json=payload, headers=headers)
  print(json.dumps(res.json(), indent=2))
  ```
</CodeGroup>

Hinweis: `result.json_content` gibt ein stringifiziertes JSON zurück. Parsen es in deinem Code, wenn du ein Objekt benötigst.

**Preisgestaltung:** `llm_extract` kostet 10 Credits pro Scrape. Um die Kosten zu senken, kannst du deine eigenen API-Schlüssel verwenden oder nutzungsbasierte Preisgestaltung aktivieren. Kontaktiere [info@olostep.com](mailto:info@olostep.com), um Zugang zu erhalten.

## Links auf der Seite extrahieren

Mit der `links_on_page`-Option kannst du alle Links extrahieren, die auf der Seite vorhanden sind, die du scrapest. Es akzeptiert die folgenden Parameter, um die extrahierten Links zu filtern und zu ordnen:

* `absolute_links` (boolean, Standard: `true`): Wenn true, werden vollständige URLs zurückgegeben (z.B. `https://example.com/page`) anstelle von relativen Pfaden (z.B. `/page`).
* `query_to_order_links_by` (string): Ordnet die zurückgegebenen Links nach ihrer Ähnlichkeit mit dem bereitgestellten Abfragetext, wobei die relevantesten Übereinstimmungen zuerst priorisiert werden.
* `include_links` (Array von Strings): Filtere extrahierte Links mit Glob-Mustern. Verwende Muster wie `*.pdf`, um Dateierweiterungen zu matchen, `/blog/*` für spezifische Pfade oder vollständige URLs wie `https://example.com/*`. Unterstützt Platzhalter (`*`), Zeichenklassen (`[a-z]`) und Alternation (`{pattern1,pattern2}`).
* `exclude_links` (Array von Strings): Schließe spezifische Links mit Glob-Mustern aus, die der gleichen Syntax wie `include_links` folgen.

## Mit der Seite interagieren mit Aktionen

Führe Aktionen vor dem Scraping aus, um mit dynamischen Seiten zu interagieren. Unterstützte Aktionen:

* `wait` mit `milliseconds`
* `click` mit `selector`
* `fill_input` mit `selector` und `value`
* `scroll` mit `direction` und `amount`

Es ist oft nützlich, `wait` vor/nach anderen Aktionen zu verwenden, um der Seite Zeit zum Laden zu geben.

### Beispiel

<CodeGroup>
  ```python Python theme={null}
  from olostep import FillInputAction, Olostep, WaitAction

  client = Olostep(api_key="YOUR_REAL_KEY")

  result = client.scrapes.create(
      url_to_scrape="https://example.com/login",
      formats=["markdown"],
      actions=[
          FillInputAction(selector="input[type=email]", value="john@example.com"),
          WaitAction(milliseconds=500),
          FillInputAction(selector="input[type=password]", value="secret"),
          {"type": "click", "selector": "button[type=\"submit\"]"},
          WaitAction(milliseconds=1500),
      ],
  )

  print(result.markdown_content)
  ```

  ```js Node theme={null}
  import Olostep from 'olostep'

  const client = new Olostep({ apiKey: 'YOUR_REAL_KEY' })

  const result = await client.scrapes.create({
    url: 'https://example.com/login',
    formats: ['markdown'],
    actions: [
      { type: 'fill_input', selector: 'input[type=email]', value: 'john@example.com' },
      { type: 'wait', milliseconds: 500 },
      { type: 'fill_input', selector: 'input[type=password]', value: 'secret' },
      { type: 'click', selector: 'button[type="submit"]' },
      { type: 'wait', milliseconds: 1500 },
    ],
  })

  console.log(result.markdown_content)
  ```

  ```bash cURL theme={null}
  curl -s -X POST "https://api.olostep.com/v1/scrapes" \
    -H "Authorization: Bearer $OLOSTEP_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "url_to_scrape": "https://example.com/login",
      "formats": ["markdown"],
      "actions": [
        { "type": "fill_input", "selector": "input[type=email]", "value": "john@example.com" },
        { "type": "wait", "milliseconds": 500 },
        { "type": "fill_input", "selector": "input[type=password]", "value": "secret" },
        { "type": "click", "selector": "button[type=\"submit\"]" },
        { "type": "wait", "milliseconds": 1500 }
      ]
    }'
  ```

  ```bash CLI theme={null}
  # Für komplexe Optionen wie Aktionen, verwende --payload-file mit einer JSON-Datei
  olostep scrape "https://example.com/login" \
    --formats markdown \
    --payload-file actions.json

  # Wo actions.json enthält:
  # {
  #   "actions": [
  #     {"type": "fill_input", "selector": "input[type=email]", "value": "john@example.com"},
  #     {"type": "wait", "milliseconds": 500},
  #     {"type": "fill_input", "selector": "input[type=password]", "value": "secret"},
  #     {"type": "click", "selector": "button[type=\"submit\"]"},
  #     {"type": "wait", "milliseconds": 1500}
  #   ]
  # }
  ```

  ```js Node (API) theme={null}
  const res = await fetch('https://api.olostep.com/v1/scrapes', {
    method: 'POST',
    headers: { 'Authorization': 'Bearer <YOUR_API_KEY>', 'Content-Type': 'application/json' },
    body: JSON.stringify({
      url_to_scrape: 'https://example.com/login',
      formats: ['markdown'],
      actions: [
        { type: 'fill_input', selector: 'input[type=email]', value: 'john@example.com' },
        { type: 'wait', milliseconds: 500 },
        { type: 'fill_input', selector: 'input[type=password]', value: 'secret' },
        { type: 'click', selector: 'button[type="submit"]' },
        { type: 'wait', milliseconds: 1500 }
      ]
    })
  })
  console.log(await res.json())
  ```

  ```python Python (API) theme={null}
  import requests, json

  endpoint = "https://api.olostep.com/v1/scrapes"
  payload = {
    "url_to_scrape": "https://example.com/login",
    "formats": ["markdown"],
    "actions": [
      {"type": "fill_input", "selector": "input[type=email]", "value": "john@example.com"},
      {"type": "wait", "milliseconds": 500},
      {"type": "fill_input", "selector": "input[type=password]", "value": "secret"},
      {"type": "click", "selector": "button[type=\"submit\"]"},
      {"type": "wait", "milliseconds": 1500}
    ]
  }
  headers = {
      "Authorization": "Bearer <YOUR_API_KEY>", 
      "Content-Type": "application/json"
  }
  res = requests.post(endpoint, json=payload, headers=headers)
  print(json.dumps(res.json(), indent=2))
  ```
</CodeGroup>

Die Antwort wird alle angeforderten Formate enthalten (z.B. `markdown_content`).

## Anwendungsfälle

Nachfolgend sind einige praktische Anwendungen von Kunden aufgeführt, die den `/scrapes` Endpunkt verwenden.

### Inhaltsanalyse & Forschung

* **Wettbewerbsanalyse**: Extrahiere Produktdetails, Preise und Funktionen von Wettbewerber-Websites
* **Marktforschung**: Analysiere Landingpages, Produktbeschreibungen und Kundenreferenzen
* **Akademische Forschung**: Sammle spezifische Daten aus wissenschaftlichen Publikationen oder Forschungsportalen
* **Rechtsdokumentation**: Extrahiere Fallstudien, Vorschriften oder rechtliche Präzedenzfälle von offiziellen Websites

### E-Commerce & Einzelhandel

* **Dynamische Preisstrategien**: Erhalte Echtzeit-Produktpreise von konkurrierenden Geschäften
* **Produktinformationsmanagement**: Extrahiere detaillierte Spezifikationen und Beschreibungen
* **Bestandsüberwachung**: Überprüfe die Produktverfügbarkeit bei anderen Einzelhändlern
* **Bewertungsanalyse**: Sammle Verbraucherfeedback und -stimmung für spezifische Produkte

### Marketing & Inhaltserstellung

* **Inhaltskuratierung**: Extrahiere relevante Artikel und Blogposts für Newsletter
* **SEO-Analyse**: Untersuche die Keyword-Nutzung, Meta-Beschreibungen und Seitenstruktur der Konkurrenz
* **Lead-Generierung**: Extrahiere Kontaktinformationen aus Unternehmensverzeichnissen oder Firmenwebseiten
* **Influencer-Forschung**: Sammle Engagement-Metriken und Inhaltsstile von Influencer-Profilen
* **Personalisierte Social-Media-Generierung**: Erstelle KI-gestützte Social-Media-Marketing durch Analyse von Kundenwebsites

### Datenanwendungen

* **AI-Trainingsdatensammlung**: Sammle spezifische Beispiele für maschinelle Lernmodelle
* **Benutzerdefinierte Wissensdatenbankerstellung**: Extrahiere Dokumentationen oder Anleitungen von Softwareseiten
* **Historische Datenarchive**: Bewahre Website-Inhalte zu bestimmten Zeitpunkten auf
* **Strukturierte Datenextraktion**: Transformiere Webinhalte in formatierte Datensätze zur Analyse

### Überwachung & Benachrichtigungen

* **Überwachung der Einhaltung von Vorschriften**: Verfolge Änderungen auf rechtlichen oder regulatorischen Websites
* **Krisenmanagement**: Überwache Nachrichtenseiten auf Erwähnungen bestimmter Ereignisse oder Organisationen
* **Ereignisverfolgung**: Extrahiere Details zu bevorstehenden Veranstaltungen von Veranstaltungs- oder Organisator-Websites
* **Überwachung des Dienststatus**: Überprüfe Dienststatusseiten für spezifische Plattformen oder Tools

### Publishing & Medien

* **Nachrichtenaggregation**: Extrahiere aktuelle Nachrichten aus offiziellen Quellen
* **Medienüberwachung**: Verfolge spezifische Themen auf Nachrichtenseiten
* **Inhaltsverifizierung**: Extrahiere Informationen zur Überprüfung von Behauptungen oder Aussagen
* **Multimedia-Extraktion**: Sammle eingebettete Videos, Bilder oder Audiodateien für Medienbibliotheken

### Finanzanwendungen

* **Investitionsforschung**: Extrahiere Finanzberichte oder Jahresberichte von Unternehmenswebsites
* **Wirtschaftsindikatoren**: Sammle Wirtschaftsdaten von Regierungs- oder Finanzinstitutionswebsites
* **Kryptowährungsdaten**: Extrahiere Echtzeit-Preise und Marktkapitalisierungsinformationen
* **Finanznachrichtenanalyse**: Überwache Finanznachrichtenseiten auf spezifische Marktsignale

### Technische Anwendungen

* **API-Dokumentationsextraktion**: Sammle technische Dokumentationen zur Referenz
* **Integrationstests**: Extrahiere Website-Elemente zur Überprüfung von Drittanbieter-Integrationen
* **Barrierefreiheitstests**: Analysiere die Website-Struktur auf Einhaltung von Barrierefreiheitsstandards
* **Webarchiverstellung**: Erfasse vollständige Website-Inhalte zur historischen Bewahrung

### Integrationsszenarien

* **CRM-Systeme**: Ergänze Kundenprofile mit Daten von Unternehmenswebsites oder LinkedIn
* **Content-Management-Systeme**: Importiere relevante externe Inhalte
* **Business-Intelligence-Tools**: Ergänze interne Daten mit externen Marktinformationen
* **Projektmanagement-Software**: Extrahiere Spezifikationen oder Anforderungen von Kundenwebsites
* **Benutzerdefinierte Dashboards**: Zeige extrahierte Daten neben internen Metriken an

## Fehlerbehandlung

Alle Fehler folgen einer gemeinsamen Umschlagform. Überprüfe `error.type` und `error.code`, um programmatisch zu verzweigen:

```json theme={null}
{
  "id": "error_abc123",
  "object": "error",
  "created": 1745673871,
  "url": "https://example.com",
  "metadata": {},
  "error": {
    "type": "...",
    "code": "...",
    "message": "..."
  }
}
```

| HTTP | `error.type`            | `error.code`            | Bedeutung                                                                                                            |
| ---- | ----------------------- | ----------------------- | -------------------------------------------------------------------------------------------------------------------- |
| 400  | `invalid_request_error` | `dns_resolution_failed` | Die Domain existiert nicht oder die URL enthält einen Tippfehler.                                                    |
| 400  | `invalid_request_error` | `invalid_url`           | Die URL ist fehlerhaft.                                                                                              |
| 502  | `invalid_request_error` | `tls_error`             | Die Website hat ein ungültiges oder inkompatibles TLS/SSL-Zertifikat. `error.detail` enthält den Low-Level-SSL-Code. |
| 504  | `request_timeout`       | `scrape_poll_timeout`   | Der Scrape wurde nicht innerhalb des \~55-Sekunden-Wartebudgets abgeschlossen.                                       |

### DNS-Fehler (400)

Die Domain wird nicht aufgelöst. Überprüfe die URL auf Tippfehler.

```json theme={null}
{
  "error": {
    "type": "invalid_request_error",
    "code": "dns_resolution_failed",
    "message": "Die URL enthält einen Tippfehler oder die Domain existiert nicht."
  }
}
```

### TLS/SSL-Fehler (502)

Die Zielwebsite hat eine fehlerhafte oder inkompatible HTTPS-Konfiguration. `error.detail` liefert den spezifischen SSL-Fehlercode für Diagnosen; `error.code` ist immer `tls_error`.

```json theme={null}
{
  "error": {
    "type": "invalid_request_error",
    "code": "tls_error",
    "detail": "err_ssl_tlsv1_alert_internal_error",
    "message": "Die Website hat den TLS-Handshake geschlossen oder abgelehnt. Der Server könnte falsch konfiguriert sein oder eine nicht unterstützte SSL/TLS-Version verwenden."
  }
}
```

### Anforderungszeitüberschreitung (504)

Der Scrape wurde nicht innerhalb des Wartebudgets abgeschlossen. Die Seite könnte langsam, bot-geschützt oder vorübergehend nicht verfügbar sein. Diese Antwort kann sicher erneut versucht werden.

```json theme={null}
{
  "error": {
    "type": "request_timeout",
    "code": "scrape_poll_timeout",
    "message": "Anforderung abgelaufen, während auf das Scrape-Ergebnis gewartet wurde. Die Seite könnte langsam, für unsere Fetcher blockiert oder vorübergehend nicht verfügbar sein."
  }
}
```

## Preisgestaltung

Scrape kostet standardmäßig 1 Credit. Wenn du auch [parsers](/features/structured-content/parsers) verwendest, variieren die Kosten je nach Parser (1-5 Credits). Wenn du [LLM extract](/features/structured-content/llm-extraction) verwendest, kostet es 10 Credits.
