Mark web pages for use with vision-language models.
## Overview **WebMarker** adds visual markings with labels to elements on a web page. This can be used for [Set-of-Mark](https://github.com/microsoft/SoM) prompting, which improves visual grounding abilities of vision-language models.  ## How it works **1. Call the `mark()` function** This marks the interactive elements on the page, and returns an object containing the marked elements, where each key is a mark label string, and each value is an object with the following properties: - `element`: The interactive element that was marked. - `markElement`: The label element that was added to the page. - `boundingBoxElement`: The bounding box element that was added to the page. You can use this information to build your prompt for the vision-language model. **2. Send a screenshot of the marked page to a vision-language model, along with your prompt** Example prompt: ```javascript let markedElements = mark(); let prompt = `The following is a screenshot of a web page. Interactive elements have been marked with red bounding boxes and labels. When referring to elements, use the labels to identify them. Return an action and element to perform the action on. Available actions: click, hover Available elements: ${Object.keys(markedElements) .map((label) => `- ${label}`) .join("\n")} Example response: click 0 `; ``` **3. Programmatically interact with the marked elements.** In a web browser (i.e. via Playwright), interact with elements as needed. For prompting or agent ideas, see the [WebVoyager](https://github.com/MinorJerry/WebVoyager) paper. ## Playwright example ```javascript // Inject the WebMarker library into the page await page.addScriptTag({ url: "https://cdn.jsdelivr.net/npm/webmarker-js/dist/main.js", }); // Mark the page and get the marked elements let markedElements = await page.evaluate(async () => await WebMarker.mark()); // Click a marked element await page.locator('[data-mark-label="0"]').click(); // (Optional) Check if page is marked let isMarked = await page.evaluate(async () => await WebMarker.isMarked()); // (Optional) Unmark the page await page.evaluate(async () => await WebMarker.unmark()); ``` ## Options ### selector A custom CSS selector to specify which elements to mark. - Type: `string` - Default: `'a[href], button, input:not([type="hidden"]), select, textarea, summary, [role="button"], [tabindex]:not([tabindex="-1"])'` ### getLabel Provide a function for generating labels. By default, labels are generated as integers starting from 0. - Type: `(element: Element, index: number) => string` - Default: `(_, index) => index.toString()` ### markAttribute A custom attribute to add to the marked elements. This attribute contains the label of the mark. - Type: `string` - Default: `"data-mark-label"` ### markPlacement The placement of the mark relative to the element. - Type: `'top' | 'top-start' | 'top-end' | 'right' | 'right-start' | 'right-end' | 'bottom' | 'bottom-start' | 'bottom-end' | 'left' | 'left-start' | 'left-end'` - Default: `'top-start'` ### markStyle A CSS style to apply to the label element. You can also specify a function that returns a CSS style object. - Type: `Partial