VLearnVibium

How to Scrape a Table with Vibium

Extract rows and cells from an HTML table with Vibium in Python — find the rows with findAll(), read each cell's text with a scoped find, and build clean structured data.

By Pramod Dutta··3 min read·Verified with Vibium 26.2
▶ Animated overview · made with Remotion

To scrape a table with Vibium, navigate to the page, grab every row with findAll(), then read each cell's text() and collect the values into structured data. findAll() returns a list of elements, so you loop over rows the same way you would loop over a Python list. No driver wrangling, no manual waits.

What is the table-scraping script?

from vibium import browser_sync as browser
 
vibe = browser.launch()
vibe.go("https://example.com/pricing")
 
row_count = len(vibe.findAll("table tbody tr"))
 
data = []
for i in range(row_count):
    row = f"table tbody tr:nth-child({i + 1})"
    cells = vibe.findAll(f"{row} td")
    data.append([cell.text() for cell in cells])
 
for record in data:
    print(record)
 
vibe.quit()

This walks every <tr> in the table body, reads each <td>, and prints one Python list per row. findAll() returns a plain list, so a :nth-child row selector lets you pull just the cells inside one row. From there you can write CSV, build dictionaries, or push the rows into a database.

How does each step work?

  1. vibe.go(url) — opens the page and waits for the load event before you read anything.
  2. vibe.findAll("table tbody tr") — returns a list of every row element. Unlike find(), which returns the first match, findAll() gives you the whole set. Here we just take its length to learn the row count.
  3. vibe.findAll(f"{row} td") — a :nth-child row selector scopes the cell lookup to a single row, so each pass pulls only that row's cells.
  4. cell.text() — reads the text content of each cell.
  5. vibe.quit() — shuts the browser down.

findAll() returns immediately and yields an empty list when nothing matches, so an empty table will not hang your script.

How do I turn rows into labeled records?

Pull the header cells once, then zip them against each row to get a list of dictionaries — far easier to work with downstream:

from vibium import browser_sync as browser
 
vibe = browser.launch()
vibe.go("https://example.com/pricing")
 
headers = [th.text() for th in vibe.findAll("table thead th")]
row_count = len(vibe.findAll("table tbody tr"))
 
records = []
for i in range(row_count):
    row = f"table tbody tr:nth-child({i + 1})"
    values = [td.text() for td in vibe.findAll(f"{row} td")]
    records.append(dict(zip(headers, values)))
 
print(records[0])  # {"Plan": "Pro", "Price": "$29", "Seats": "10"}
 
vibe.quit()

How do I handle a table that loads after the page?

If the table is rendered by JavaScript after load, wait for the first row to become visible before you scrape. findAll() resolves immediately and would return an empty list if you call it too early, so wait on a single element first with waitUntil():

vibe.find("table tbody tr").wait_until("visible")  # wait until the first row shows
row_count = len(vibe.findAll("table tbody tr"))

wait_until() polls until the element reaches the requested state (visible, hidden, attached, or detached) or the timeout is hit, so a slow-loading table will not race your script.

Tips for reliable table scraping

  • Scope your selectors to the specific table (an id or class) so a layout change elsewhere does not break you.
  • Read attr() when the useful value lives in an attribute, for example cell.find("a").attr("href") for a link.
  • Save as you go — write each row to a file inside the loop for large tables so a crash does not lose everything.

Next steps

Frequently asked questions

How do I scrape an HTML table with Vibium?

Navigate to the page, use findAll() to get every row element, then read each cell with a scoped find() and text() to pull the values. Collect the cells into a list of dictionaries or rows for clean, structured output you can save or process.

How does Vibium select multiple elements at once?

Use vibe.findAll(css) to get a list of every matching element, where find() returns just the first match. findAll() returns immediately with an empty list when nothing matches, so you can loop over rows or cards without extra waiting code.

Can I scrape a table without writing CSS selectors?

Often, yes. Vibium's find() also accepts semantic options like role and text, so you can target elements by their accessible role. For tabular data, though, CSS selectors targeting tr and td cells are usually the simplest and fastest approach.

Vibium is created by Jason Huggins. This is an independent tutorial — see the official Vibium site and GitHub repo for canonical docs.

Related guides