Fruitful Docs
GuidesCapture

Choose an extractor engine

Interrogate the page before writing selectors, and pick the cheapest engine that reads it reliably.

A binding configures one platform engine. The engine is Fruitful code that reads a page; the binding is your data that tells it what to read. Which engine you pick decides how stable the package is and what the route may declare.

The engines

EngineReadsUse it for
dom@1a browser snapshotcollections: lists of entries you select with CSS
reader@1a browser snapshotitems: a whole article the platform reads into a webDocument
media@1the URLitems: video and audio through the platform media pipeline
rss@1, http@1a fetched bodydeclared today; their runtimes are the next slice

The full table with what each emits is on Extractor engines.

Interrogate the page first

Before writing a selector, look at what the site already publishes. Capture the page once and read the capture's WARC and DOM, in this order:

  1. A feed or API the page advertises. A <link rel="alternate" type="application/rss+xml"> tag, or a JSON endpoint in the WARC that carries the same entries with stable ids. These are what rss@1 and http@1 will read. Until their runtimes land, record the evidence (URL, response shape, id field) in the package notes and fall through.
  2. Embedded structured data. application/ld+json, __NEXT_DATA__, serialized store state, or data-* attributes carrying ids and timestamps. A dom@1 binding that reads attributes is more stable than one that reads visible text.
  3. Visible DOM. Only then write selectors over rendered markup, preferring data-testid, ARIA roles, and semantic elements over class names.

Collections use dom; items use the first-party bindings

A collection route needs an engine that feeds the transform, which today means dom@1. An item route that should be read whole uses a first-party binding instead of a package binding:

"bindings": [
  { "id": "front-page", "package": "com.ycombinator.news.binding.front-page@^0.3.0" },
  { "id": "reader", "package": "app.fruitful.binding.reader@^1.0.0" }
]

app.fruitful.binding.reader, .video, and .audio are already in every registry. Pin them; never copy them into your definition.

What the engine allows on the route

Engines that read a snapshot open a browser, so their routes may declare login, load, ready, on, and scroll. Engines that never open the page reject all five. The registry enforces this at publish.

Reference: bindingDependency, Binding package.

On this page