By Sagar Shankaran, Founder of CallSphere
Discover how GPT Vision identifies interactive web elements visually, eliminating the need for CSS selectors or XPaths. Learn bounding box extraction, OCR-free text reading, and visual element classification.
Key takeaways
Every web automation engineer has experienced it: your carefully crafted CSS selector button.btn-primary.submit-form stops working because the development team renamed the class to btn-action-submit. XPaths break when a new div wrapper is added. Data attributes get removed during refactors.
GPT Vision sidesteps this entire class of problems. Instead of relying on implementation details of the HTML structure, it identifies elements the way a human does — by how they look and what text they contain.
The most reliable approach is to ask GPT-4V to return structured data about every interactive element it detects on the page.
Hear it before you finish reading
Talk to a live CallSphere AI voice agent in your browser — 60 seconds, no signup.
flowchart LR
INPUT(["User intent"])
PARSE["Parse plus<br/>classify"]
PLAN["Plan and tool<br/>selection"]
AGENT["Agent loop<br/>LLM plus tools"]
GUARD{"Guardrails<br/>and policy"}
EXEC["Execute and<br/>verify result"]
OBS[("Trace and metrics")]
OUT(["Outcome plus<br/>next action"])
INPUT --> PARSE --> PLAN --> AGENT --> GUARD
GUARD -->|Pass| EXEC --> OUT
GUARD -->|Fail| AGENT
AGENT --> OBS
style AGENT fill:#4f46e5,stroke:#4338ca,color:#fff
style GUARD fill:#f59e0b,stroke:#d97706,color:#1f2937
style OBS fill:#ede9fe,stroke:#7c3aed,color:#1e1b4b
style OUT fill:#059669,stroke:#047857,color:#fff
from pydantic import BaseModel
from openai import OpenAI
class DetectedElement(BaseModel):
element_type: str # button, link, text_input, checkbox, etc.
label: str # visible text or aria description
x_center: int # estimated center x coordinate
y_center: int # estimated center y coordinate
width: int # estimated width in pixels
height: int # estimated height in pixels
confidence: str # high, medium, low
is_enabled: bool
context: str # surrounding context or section
class ElementDetectionResult(BaseModel):
page_description: str
elements: list[DetectedElement]
total_interactive_count: int
client = OpenAI()
def detect_elements(screenshot_b64: str) -> ElementDetectionResult:
"""Detect all interactive elements in a screenshot."""
response = client.beta.chat.completions.parse(
model="gpt-4o",
messages=[
{
"role": "system",
"content": (
"You are a UI element detector. The screenshot is "
"1280x720 pixels. Identify every interactive element: "
"buttons, links, input fields, checkboxes, dropdowns, "
"toggles, and tabs. For each element, estimate its "
"center coordinates and bounding box dimensions. "
"Report confidence as high/medium/low."
),
},
{
"role": "user",
"content": [
{
"type": "text",
"text": "Detect all interactive elements.",
},
{
"type": "image_url",
"image_url": {
"url": f"data:image/png;base64,{screenshot_b64}",
"detail": "high",
},
},
],
},
],
response_format=ElementDetectionResult,
)
return response.choices[0].message.parsed
Once you have structured detection results, filtering for specific element types becomes straightforward Python.
def find_buttons(result: ElementDetectionResult) -> list[DetectedElement]:
"""Find all detected buttons."""
return [
el for el in result.elements
if el.element_type == "button" and el.is_enabled
]
def find_element_by_label(
result: ElementDetectionResult, label: str
) -> DetectedElement | None:
"""Find an element by its visible label text."""
label_lower = label.lower()
for el in result.elements:
if label_lower in el.label.lower():
return el
return None
def find_inputs_in_region(
result: ElementDetectionResult,
x_min: int, y_min: int, x_max: int, y_max: int
) -> list[DetectedElement]:
"""Find input fields within a specific page region."""
return [
el for el in result.elements
if el.element_type in ("text_input", "textarea", "dropdown")
and x_min <= el.x_center <= x_max
and y_min <= el.y_center <= y_max
]
GPT-4V reads text directly from screenshots without requiring a separate OCR pipeline. This is particularly useful for extracting text from elements that are difficult to access via the DOM, such as text rendered in canvas, SVG labels, or styled components where the text node is deeply nested.
class ExtractedText(BaseModel):
text: str
source_type: str # heading, paragraph, label, button_text, etc.
approximate_y: int # vertical position for ordering
class PageTextExtraction(BaseModel):
texts: list[ExtractedText]
def extract_visible_text(screenshot_b64: str) -> PageTextExtraction:
"""Extract all visible text from a screenshot."""
response = client.beta.chat.completions.parse(
model="gpt-4o",
messages=[
{
"role": "system",
"content": (
"Extract all visible text from this web page screenshot. "
"Include headings, paragraph text, button labels, link "
"text, form labels, and any other readable text. Order "
"by vertical position (top to bottom)."
),
},
{
"role": "user",
"content": [
{
"type": "text",
"text": "Extract all text from this page.",
},
{
"type": "image_url",
"image_url": {
"url": f"data:image/png;base64,{screenshot_b64}",
"detail": "high",
},
},
],
},
],
response_format=PageTextExtraction,
)
return response.choices[0].message.parsed
Combining element detection with Playwright, you can build a robust click resolver that finds elements by visual description rather than selectors.
from playwright.async_api import Page
async def click_element_by_description(
page: Page, description: str, screenshot_b64: str
) -> bool:
"""Click an element found by visual description."""
result = detect_elements(screenshot_b64)
target = find_element_by_label(result, description)
if target is None:
print(f"Element '{description}' not found")
return False
if target.confidence == "low":
print(f"Warning: low confidence match for '{description}'")
await page.mouse.click(target.x_center, target.y_center)
return True
Visual detection struggles with certain scenarios. Overlapping elements, very small icons without text labels, and elements hidden behind hover states are all challenging. For these cases, combine vision with a quick DOM check: use GPT-4V for the initial scan, then fall back to page.query_selector() for edge cases where visual detection reports low confidence.
Still reading? Stop comparing — try CallSphere live.
CallSphere ships complete AI voice agents per industry — 14 tools for healthcare, 10 agents for real estate, 4 specialists for salons. See how it actually handles a call before you book a demo.
GPT-4V sees whatever is rendered in the screenshot, including iframe content. However, it cannot distinguish iframe boundaries, so it might report elements as clickable even when they require switching to the iframe context in Playwright first. Capture separate screenshots of iframe contents when precision matters.
For standard web UI elements, GPT-4V performs comparably to specialized models like YOLO trained on UI datasets. Its advantage is zero-shot generalization — it handles unusual designs, custom components, and non-standard layouts without any training. Specialized models are faster and cheaper per inference but require training data for each UI pattern.
Yes. Set the Playwright viewport to a mobile size (e.g., 375x812) and GPT-4V will detect elements in the mobile layout. Be aware that hamburger menus, bottom sheets, and slide-out panels may hide elements until user interaction reveals them.
#ElementDetection #GPTVision #SelectorFree #WebAutomation #VisualAI #BoundingBox #OCRFree #AgenticAI

Written by
Sagar Shankaran· Founder, CallSphere
LinkedInSagar Shankaran is the founder of CallSphere, where he builds production AI voice and chat agents deployed across healthcare, hospitality, real estate, and home services. He writes about agentic AI, LLM engineering, and shipping voice agents that handle real calls in production.
See how AI voice agents work for your industry. Live demo available -- no signup required.
Build an AI agent that reads source documents using OCR and vision models, maps extracted data to web form fields, fills forms automatically, and validates entries with intelligent error correction.
Explore how UFO captures, annotates, and sends Windows application screenshots to GPT-4V for UI element detection, control identification, and intelligent action mapping at each automation step.
Build a complete screenshot-action loop where GPT-4V analyzes web pages, decides where to click, and navigates autonomously. Learn coordinate extraction, click targeting, and navigation decision-making.
Learn how to capture web page screenshots and send them to GPT-4 Vision for element identification, layout understanding, and structured analysis that powers browser automation agents.
Step-by-step guide to building a browser automation agent with Claude Computer Use — from SDK setup and screenshot capture to executing click, type, and scroll actions for real web navigation tasks.
Browser automation agents that can navigate any website are now available as consumer products from Convergence, MultiOn, and Induced AI, moving beyond developer tools to everyday users.
© 2026 CallSphere Inc. All rights reserved.
Made within San Francisco
Watch how CallSphere handles real customer calls, schedules appointments, and processes payments — live.