What is extract()?

page.extract("extract the name of the repository");
extract grabs structured data from a webpage. You can define your schema with zod (TypeScript) or pydantic (Python). If you do not want to define a schema, you can also call extract with just a natural language prompt, or call extract with no parameters.

Why use extract()?

For TypeScript, the extract schemas are defined using zod schemas.For Python, the extract schemas are defined using pydantic models.

Using extract()

Single object Extraction

Here is how an extract call might look for a single object:
const item = await page.extract({
  instruction: "extract the price of the item",
  schema: z.object({
    price: z.number(),
  }),
});
Your output schema will look like:
{ price: number }

List of objects Extraction

Here is how an extract call might look for a list of objects.
const apartments = await page.extract({
  instruction:
    "Extract ALL the apartment listings and their details, including address, price, and square feet.",
  schema: z.object({
    list_of_apartments: z.array(
      z.object({
        address: z.string(),
        price: z.string(),
        square_feet: z.string(),
      }),
    ),
  })
})

console.log("the apartment list is: ", apartments);
Your output schema will look like:
list_of_apartments: [
    {
      address: "street address here",
      price: "$1234.00",
      square_feet: "700"
    },
    {
        address: "another address here",
        price: "1010.00",
        square_feet: "500"
    },
    ...
]

Prompt-only Extraction

You can call extract with just a natural language prompt:
const result = await page.extract("extract the name of the repository");
When you call extract with just a prompt, your output schema will look like:
{ extraction: string }

Extract with no parameters

Here is how you can call extract with no parameters.
const pageText = await page.extract();
Output schema:
{ page_text: string }
Calling extract with no parameters will return hierarchical tree representation of the root DOM. This will not be passed through an LLM. It will look something like this:
Accessibility Tree:
[0-2] RootWebArea: What is Stagehand? - 🤘 Stagehand
  [0-37] scrollable
    [0-118] body
      [0-241] scrollable
        [0-242] div
          [0-244] link: 🤘 Stagehand home page light logo
            [0-245] span
              [0-246] StaticText: 🤘 Stagehand
              [0-247] StaticText: home page

Best practices

Extract with Context

You can provide additional context to your schema to help the model extract the data more accurately.
const apartments = await page.extract({
 instruction:
   "Extract ALL the apartment listings and their details, including address, price, and square feet.",
 schema: z.object({
   list_of_apartments: z.array(
     z.object({
       address: z.string().describe("the address of the apartment"),
       price: z.string().describe("the price of the apartment"),
       square_feet: z.string().describe("the square footage of the apartment"),
     }),
   ),
 })
})
To extract links or URLs, in the TypeScript version of Stagehand, you’ll need to define the relevant field as z.string().url(). In Python, you’ll need to define it as HttpUrl.
Here is how an extract call might look for extracting a link or URL. This also works for image links.
const extraction = await page.extract({
  instruction: "extract the link to the 'contact us' page",
  schema: z.object({
    link: z.string().url(), // note the usage of z.string().url() here
  }),
});

console.log("the link to the contact us page is: ", extraction.link);
Inside Stagehand, extracting links works by asking the LLM to select an ID. Stagehand looks up that ID in a mapping of IDs -> URLs. When logging the LLM trace, you should expect to see IDs. The actual URLs will be included in the final ExtractResult.

Troubleshooting

Next steps