---
title: HTML Extract
description: Pull values out of HTML with CSS selectors
---

Pull values out of HTML with CSS selectors, from one value to a whole list of rows.

## Try it

## What it does

HTML Extract reads the HTML you put in its **HTML** field and finds elements in it with CSS selectors. It has two modes:

* **Single value** finds the first element that matches **Selector** and returns its text, its inner HTML or one of its attributes.
* **Repeating list** finds every element that matches **Container Selector** (each search result, table row or card) and builds one item per match, reading each of your **Fields** from inside that container.

Text is trimmed of surrounding spaces. Returned HTML is cleaned of scripts and other unsafe content. The HTML is only read, never run, and it can be up to about 2 MB.

## When to use it

* Pull a title, price or link out of a page you fetched.
* Turn a listing page (search results, a table, a feed) into one item per row with clean fields.
* To read straight from the page open in your browser, [Get Element Data](/nodes/extension/getelementdata/) may be simpler. To match text patterns rather than page structure, use [Regex](/nodes/builtin/datatransformation/regex/).

## Inputs and settings

* **HTML**: bind it with an expression. After an [Http Request](/nodes/builtin/core/http-request/), the page is in `{{ $input.data }}`.
* **Selector** and **Container Selector** take standard CSS selectors, for example `h1.title`, `#price` or `ul.results > li`.
* In list mode, each field's **Selector** is searched inside its container, so keep it short, for example `a.title` rather than the full path.
* **Attribute** names the attribute to read, for example `href` for links or `src` for images.

## Outputs

* **Single value** returns one item, `{ "value": ... }`. `value` is empty (undefined) when nothing matched or the element lacks the attribute.
* **Repeating list** returns one item per matched container, with one field per entry in **Fields**. The next node runs once per row. If no container matches, there are no items.

## Dependencies and credentials

None. This node needs no connection and has no slots for other nodes.

## Example workflow

1. [Http Request](/nodes/builtin/core/http-request/) with **URL** set to a search results page.
2. **HTML Extract** with **HTML** `{{ $input.data }}`, **Mode** *Repeating list* and **Container Selector** `ul.results > li`.
3. Under **Fields**, add `title` (Selector `a.title`, Return *Text*) and `link` (Selector `a.title`, Return *Attribute*, Attribute `href`).
4. [Limit](/nodes/builtin/datatransformation/limit/) keeps the first 10 rows for the next steps.

## Common issues

* **"No selector given. Fill in the Selector field."** or **"No container selector given. Fill in the Container Selector field."** Fill in the selector for the mode you chose.
* **"Invalid CSS selector: "..."."** The selector has a typo. Test it in your browser's developer tools first.
* **"Return is set to Attribute but no attribute name was given."** Fill in **Attribute**, for example `href`.
* **"Input is ... bytes, larger than the 2000000-byte limit this node will parse."** The HTML is over about 2 MB. Extract a smaller part of the page first.
* **The value is empty though the element is visible in the browser.** The page builds that part with scripts after it loads, so it is not in the fetched HTML. Read it from the live page with [Get All HTML](/nodes/extension/getallhtml/) instead.

## Recipes with this node

## Related nodes

* [Http Request](/nodes/builtin/core/http-request/): fetch the HTML to extract from.
* [Get HTML from Link](/nodes/builtin/core/gethtmlfromlink/): get the HTML of a page by its URL.
* [Markdown](/nodes/builtin/datatransformation/markdown/): turn HTML into readable Markdown.
* [Regex](/nodes/builtin/datatransformation/regex/): match text patterns instead of page structure.