ScreenshotNeo

BlogEngineering

Selenium News and Updates: A Smattering of Selenium 89

A Smattering of Selenium #89 is a June 2012 link roundup by Adam Goucher, not a Selenium 89 software release. Here is what it covered and how to read it today.

By the ScreenshotNeo team4 October 202610 min read

“A Smattering of Selenium #89” is a short community link roundup published on June 18, 2012, by Adam Goucher. It is not an announcement for Selenium 89, a software version. The post points readers to six articles and event resources spanning browser performance testing, test login design, Ruby testing syntax, event recordings, and Python topics. Read the archived roundup.

What “Selenium 89” means here

The number 89 identifies the installment in the recurring “A Smattering of Selenium” blog series. The post is an editorial collection of links with brief comments, rather than a Selenium release bulletin, changelog, or tutorial. The archived series places it among neighboring installments such as #88 and #90.

That distinction matters when searching for Selenium news: a search result containing “Selenium” and “89” may refer to this issue number, not a browser driver or framework version. The post documents what its author found worth sharing in June 2012; it does not establish what Selenium supports today.

The six items in the roundup

  1. “Automate Page Load Performance Testing with Firebug and Selenium.” The title indicates a discussion of page-load performance testing using Firebug and Selenium. Goucher notes that the subject was not new but was timely for him. The archive does not provide benchmark results, a tested method, or an endorsement, so none should be inferred from the link.
  2. “Speed up your features with a backdoor login route.” Goucher describes this as an older post about a subject he had needed to explain repeatedly. The title alone does not establish how the login route works or whether its design is secure. Treat it as a link to investigate, not as current security guidance.
  3. “RSpec’s New Expectation Syntax.” The linked item explains what the syntax is and why it exists. This is the Ruby testing topic in the roundup.
  4. “Slides & Videos from LDNSE #6.” This points to event media from the sixth LDNSE event. The archive identifies the material as slides and videos but does not summarize the talks.
  5. “Python Timer Class – Context Manager for Timing Code Blocks.” Goucher says it reminded him to use context managers more often. The roundup does not describe the implementation, so the title is the safe boundary for a technical summary.
  6. “Overloading Python list comprehension.” Goucher calls it an interesting experiment, with a qualified aside. It is presented as an experiment rather than a recommended production technique.

The destinations for several of these links were unavailable during research. Their titles and Goucher’s brief descriptions are therefore the reliable scope of this summary; implementation details, present-day availability, and results should be checked at the original pages if those links are accessible.

How to use this roundup as a developer

Read it as an archive of topics and community attention, not as a source of current setup instructions. Its value is in discovering questions that were being discussed across the testing ecosystem in 2012: measuring page loads, arranging test authentication, evolving assertion syntax, sharing conference knowledge, and exploring Python idioms.

  • For historical research, preserve the publication date and author when citing it.
  • For implementation decisions, follow the original linked article and verify that its tools and APIs still apply.
  • For Selenium behavior or supported features, use current Selenium documentation and release announcements rather than inferring from this roundup.
  • Do not treat “backdoor login route” as an endorsement or security pattern; the roundup does not supply enough detail to assess it.
  • Do not infer a performance gain from the Firebug/Selenium article title. No measurement is reported in the archive.

How it fits with current Selenium news

Selenium has continued to publish project news and releases since 2012. Its official news index reports Selenium 4.49 released on September 9, 2026, and describes an upcoming change for Selenium 4.51: ExpectedCondition will stop implementing Guava’s Function interface. Those are separate, current project updates; they are not contents of the 2012 #89 roundup. See the official Selenium blog for the current index and the Selenium repository release notes for release activity.

In a September 29, 2026 post, Selenium contributor David Burns wrote: “A lot of Selenium code is now written by coding agents, and it is wrong in the same handful of ways every time.” That observation belongs to his recent post about documentation and coding agents, not to Adam Goucher’s 2012 roundup. Find it in the Selenium blog archive.

Capture a page from a Selenium-related article

If you are documenting an old article or comparing how a page renders, Selenium can open the page and save a screenshot. This Python example uses Selenium 4 with Chrome in headless mode. Install the package with python -m pip install selenium and make sure a compatible Chrome browser is available. Selenium Manager can handle driver setup for supported installations.

from pathlib import Path
from selenium import webdriver
from selenium.webdriver.chrome.options import Options

url = "https://selenium.dev/blog/2012/a-smattering-of-selenium-89/"
options = Options()
options.add_argument("--headless")
options.add_argument("--window-size=1440,1000")

# Selenium 4: Selenium Manager can discover or obtain a compatible driver.
with webdriver.Chrome(options=options) as driver:
    driver.set_page_load_timeout(45)
    driver.get(url)
    Path("selenium-smattering-89.png").write_bytes(driver.get_screenshot_as_png())

This captures the current rendering of the archived URL, not a historical 2012 screenshot. A viewport screenshot captures the current viewport; Selenium’s standard screenshot method does not itself create a full-page image. For an element-specific capture, locate the element and call its screenshot method:

from selenium.webdriver.common.by import By

with webdriver.Chrome(options=options) as driver:
    driver.get(url)
    article = driver.find_element(By.TAG_NAME, "article")
    article.screenshot("article.png")

Use a selector that matches the actual page structure. A missing element raises NoSuchElementException; dynamic pages may require an explicit wait before locating it. Selenium’s official documentation covers WebDriver usage and wait strategies.

Equivalent calls with cURL, Python, and Node.js

These examples call Selenium’s WebDriver remotely only when you provide a WebDriver endpoint, such as a Selenium Grid endpoint. Start a browser session through that endpoint, navigate to the page, then request a screenshot from the session. Replace http://localhost:4444 with your endpoint. The session creation payload shown here uses the W3C WebDriver protocol and Chrome capabilities.

curl -sS -X POST http://localhost:4444/session \
  -H 'Content-Type: application/json' \
  -d '{"capabilities":{"alwaysMatch":{"browserName":"chrome","goog:chromeOptions":{"args":["--headless","--window-size=1440,1000"]}}}}'

Read the returned sessionId, then navigate and retrieve the base64-encoded PNG:

curl -sS -X POST http://localhost:4444/session/SESSION_ID/url \
  -H 'Content-Type: application/json' \
  -d '{"url":"https://selenium.dev/blog/2012/a-smattering-of-selenium-89/"}'

curl -sS http://localhost:4444/session/SESSION_ID/screenshot

The screenshot endpoint returns JSON with a base64 value. Decode that value to save the PNG. For reliable scripting, parse JSON rather than copying the response manually.

import base64
import requests

base = "http://localhost:4444"
s = requests.post(f"{base}/session", json={
    "capabilities": {"alwaysMatch": {
        "browserName": "chrome",
        "goog:chromeOptions": {"args": ["--headless", "--window-size=1440,1000"]}
    }}
}, timeout=30).json()["value"]["sessionId"]
try:
    requests.post(f"{base}/session/{s}/url", json={
        "url": "https://selenium.dev/blog/2012/a-smattering-of-selenium-89/"
    }, timeout=60).raise_for_status()
    result = requests.get(f"{base}/session/{s}/screenshot", timeout=30)
    result.raise_for_status()
    open("selenium-smattering-89.png", "wb").write(
        base64.b64decode(result.json()["value"])
    )
finally:
    requests.delete(f"{base}/session/{s}", timeout=15)
const endpoint = 'http://localhost:4444';
const created = await fetch(`${endpoint}/session`, {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ capabilities: { alwaysMatch: {
    browserName: 'chrome',
    'goog:chromeOptions': { args: ['--headless', '--window-size=1440,1000'] }
  } } })
});
if (!created.ok) throw new Error(`Session creation failed: ${created.status}`);
const { value: { sessionId } } = await created.json();
try {
  const nav = await fetch(`${endpoint}/session/${sessionId}/url`, {
    method: 'POST', headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ url: 'https://selenium.dev/blog/2012/a-smattering-of-selenium-89/' })
  });
  if (!nav.ok) throw new Error(`Navigation failed: ${nav.status}`);
  const shot = await fetch(`${endpoint}/session/${sessionId}/screenshot`);
  if (!shot.ok) throw new Error(`Screenshot failed: ${shot.status}`);
  const { value: base64 } = await shot.json();
  const fs = await import('node:fs/promises');
  await fs.writeFile('selenium-smattering-89.png', Buffer.from(base64, 'base64'));
} finally {
  await fetch(`${endpoint}/session/${sessionId}`, { method: 'DELETE' });
}

Waits, page readiness, and capture choices

A successful navigation command does not guarantee every image or client-rendered component is ready. Use an explicit wait for the content you need instead of adding a long fixed sleep. For example:

from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

with webdriver.Chrome(options=options) as driver:
    driver.get(url)
    WebDriverWait(driver, 15).until(
        EC.presence_of_element_located((By.TAG_NAME, "article"))
    )
    driver.save_screenshot("page.png")

For a full-page capture, WebDriver’s standard screenshot endpoint may be limited to the viewport, depending on the browser and driver. Options include capturing and stitching viewport tiles in your own code, using browser-specific support, or using a screenshot service with full-page capture. Confirm dimensions and clipping on the browser and driver versions you deploy.

Or skip the browser setup

ScreenshotNeo takes a screenshot with one GET request. Its API documentation lists the capture options and response behavior. For example, with cURL:

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://selenium.dev/blog/2012/a-smattering-of-selenium-89/ -o shot.webp

ScreenshotNeo accepts cookie and consent banners like a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each step can be turned off. Bot checks, blank pages, timeouts, failed loads, and cache hits cost nothing, and response headers identify the page verdict and billing status. Its MCP server lets Claude, Cursor, and other MCP clients use take_screenshot, get_page_info, and capture_pdf. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000.

import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://selenium.dev/blog/2012/a-smattering-of-selenium-89/"}, timeout=90)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://selenium.dev/blog/2012/a-smattering-of-selenium-89/' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

See ScreenshotNeo for the service and create a free account to get 1,000 screenshots a month with no card.

Troubleshooting browser captures

Symptom Likely cause Fix
Chrome driver or session fails to start Browser and driver mismatch, unavailable Chrome, or a remote endpoint that is not running. Use a supported browser installation, let Selenium Manager resolve the driver where available, or verify the Grid endpoint and capabilities.
Navigation times out The page is slow, network access is blocked, or the configured page-load timeout is too short. Check the URL from the capture environment, set a suitable timeout, and wait for the specific content needed rather than assuming all network activity will stop.
Screenshot is blank or incomplete Capture occurred before the relevant content rendered, a bot check appeared, or the viewport missed the target. Wait for a visible content element, inspect the page state, and set an intentional viewport size.
Element lookup fails The selector does not match, the content is in a frame, or it has not appeared yet. Check the selector in the rendered DOM, switch into the correct frame when needed, and use an explicit wait.
Full page is clipped The standard screenshot captures the viewport rather than the entire document. Use browser-specific full-page capture, tile and stitch, or a capture service that supports full-page screenshots.
Remote screenshot response is an error Invalid session ID, malformed request body, or session already closed. Use the session ID returned by session creation, follow the W3C endpoint shape, and keep the session open until the screenshot response is saved.

Performance, reliability, and cost

With Selenium, each capture requires browser startup or an available remote session, navigation, readiness checks, screenshot retrieval, and cleanup. Reusing a managed browser session can reduce startup work, while isolated sessions reduce state leakage between jobs. Always close sessions in a finally block or context manager so failures do not leave browsers consuming resources.

For reproducible captures, pin the browser environment, viewport, locale, timezone, and any relevant authentication state. Pages can change over time, and a current capture of an archived post reflects the page as served now. Dynamic ads, consent prompts, network conditions, and browser rendering can also change pixels. Store the URL, timestamp, browser version, viewport, and capture outcome alongside images when the screenshot is evidence or test output.

Selenium itself is open source; operational cost depends on where browsers run and how many concurrent sessions your workload needs. A managed screenshot API can avoid maintaining browser infrastructure. ScreenshotNeo offers a free tier of 1,000 shots per month and paid tiers from $5 for 3,000; annual billing gives two months free, and every feature is available on every plan. Its other options include full-page captures with lazy images loaded, element capture, PDF, custom waits and CSS, headers and cookies, caching, signed links, asynchronous jobs, bulk capture up to 100 URLs per call, and a usage API. See the documentation for exact parameter names and behavior.

FAQ

Was Selenium 89 released in June 2012?

No. “89” is the roundup’s issue number. The post is dated June 18, 2012, and is not a software release notice.

Who wrote “A Smattering of Selenium #89”?

Adam Goucher wrote the archived post.

Does the post report Selenium performance benchmarks?

No. It links to an item whose title concerns page-load performance testing, but the roundup itself reports no benchmark result.

Are the six linked items current documentation?

No. They are links collected in 2012. Verify current tooling and practices against current primary documentation before applying them.

Where should I look for present-day Selenium releases?

Use the official Selenium blog and the project’s release notes.