Using Codex and Playwright When There Is No API

Everybody likes an API. It is the clean version of an integration: documented endpoints, structured responses, credentials meant for software, and hopefully somebody else’s problem when the implementation changes.

But plenty of useful systems do not have one. Or they have an API that covers part of the product but not the screen a team actually needs. The data is there, behind a normal login, and somebody is opening a browser and copying it into a spreadsheet.

That is a good place for browser automation.

We have been looking at a practical combination of Playwright and Codex for this kind of work. Playwright drives a real Chrome browser. Codex can work with a browser exposed over the Chrome DevTools Protocol (CDP), which makes it useful for exploring an application and helping build the automation. The important piece is that the login stays human: someone who is authorized to use the site signs in and completes MFA themselves. The automated job uses the resulting browser session; it does not try to get around the login.

A concrete example is recording live odds from sportsbooks such as FanDuel or BetMGM. If an organization is allowed to collect and use the data, that is a much better job for a computer than for someone watching pages and updating a sheet all day.

The browser is sometimes the integration

This is not an argument to scrape everything. If there is an official API that does the job, use it. It is almost always less fragile and easier to support.

But sometimes the browser is the only interface available to the user. A person can log in, look at a live market, and see the numbers, but there is no supported endpoint for getting the same information into an internal system. In that situation, the browser can be the boundary between the site and your workflow.

There are obvious limits. The account needs to be authorized, and the intended use needs to comply with the site’s terms, contracts, and applicable law. That matters especially for sportsbooks, where access and permitted use can vary by operator and jurisdiction. This is not a way to bypass MFA, CAPTCHAs, rate limits, or other controls.

Getting a logged-in browser session

Playwright is a browser automation framework. It can launch Chromium or Chrome, navigate pages, click buttons, fill forms, and read what the page renders.

The feature that makes authenticated automation workable is a persistent browser profile. Instead of starting fresh every time, Playwright launches Chrome with the same profile directory. That lets it retain browser state such as cookies and sessions when the site permits it.

The first run is simple: launch a visible browser, log in normally, handle the two-factor prompt, and make sure the page you need is available. After that, the job can reopen that same profile. It can run visibly while somebody is building or debugging it, then run headlessly when it is ready to collect data on a schedule.

import { chromium } from "playwright";

const userDataDir = "/secure/path/to/browser-profile";
const context = await chromium.launchPersistentContext(userDataDir, {
  channel: "chrome",
  headless: false, // first run: let the account owner log in
});

const page = await context.newPage();
await page.goto("https://example.com/login");

// The authorized user completes sign-in and MFA in this browser window.

That profile directory is sensitive. It may contain an active session, so treat it like a credential: keep it in approved storage, restrict who can access it, and do not put it in source control or logs. Also plan for it to expire. The site decides how long a session lasts. If the job finds a login page again, it should stop and let a person reauthenticate.

Asking Codex to do the tedious part

The page is usually the part that makes these projects annoying. Modern web applications load data after the page appears, change the DOM as markets update, and use selectors that are not obvious until you can inspect the live application.

This is where Codex helps. With the authenticated browser connected over CDP, you can ask it to inspect the page, find the market and selection elements, and build the Playwright script around what is actually there. It is much faster than guessing at selectors from a screenshot or trying to reverse engineer an undocumented backend.

A reasonable first prompt is something like:

Set up Playwright with a persistent Chrome profile and launch it visibly so I can log in. Once I have an authenticated session, use that session to inspect the live odds page and build a script that records the event, market, selection, displayed odds, and collection time.

Codex is helping with the implementation; it is not replacing the account holder. Keep that line clear. It should not be asked to find credentials, solve MFA, or work around controls the site has put in place.

A live-odds collector

Say the job is to keep an internal, timestamped record of odds for a set of games and markets.

First decide what an observation is. At a minimum, it will probably include the sportsbook, event, market, selection, displayed odds, the source page, and the time the value was seen. That last field matters: a number collected at 2:00 PM is not the same thing as a number collected five minutes later.

Next, use the visible browser session to get to the right market and let Codex inspect the rendered page. The job needs to know when the market is actually loaded, how a suspended or unavailable price is represented, and which labels or attributes are stable enough to use as selectors. Prefer user-facing labels where possible over a long chain of generated CSS classes that will disappear in the next redesign.

Once that is understood, the collector can launch the same persistent profile in headless mode, visit only the pages it needs, validate what it finds, and write normalized records to a database or queue.

const context = await chromium.launchPersistentContext(userDataDir, {
  channel: "chrome",
  headless: true,
});
const page = await context.newPage();

await page.goto(targetMarketUrl, { waitUntil: "domcontentloaded" });
await page.getByRole("heading", { name: /live odds/i }).waitFor();

const collectedAt = new Date().toISOString();
const observations = await page.locator("[data-market]").evaluateAll((markets) =>
  markets.map((market) => ({
    market: market.getAttribute("data-market"),
    text: market.textContent?.trim(),
    collectedAt,
  }))
);

The code above is deliberately generic. The real selectors should come from the target site and should be tested against its actual states. The useful outcome is not just a script that reads a page once. It is a small internal data source that dashboards, reports, or models can rely on without each one having to understand the sportsbook’s UI.

The unglamorous stuff is what makes it work

A browser job will change when the website changes. That is normal. The difference between a useful integration and a fragile script is how it behaves on a bad day.

Keep the browser profile locked down. Save where each observation came from and when it was collected. Alert when the job suddenly gets no results, sees a login screen, or returns far fewer records than normal. And give somebody a straightforward way to rerun the visible browser and refresh the session.

That is enough to turn a manual task into something dependable without pretending the website is an API.

For companies sitting on useful data behind logins, this is a practical option: a person handles the authorization once, Playwright keeps the browser state, and Codex speeds up the work of turning what is on the screen into structured data.

AI-Powered Chrome Extensions for the Web Apps You Can't Replace

There has been a lot of discussion recently about companies using AI to build internal tools that replace SaaS licenses. That is interesting, but it misses a big category of software: the web apps you cannot replace.

Sometimes the constraint is technical. More often, it is not. An insurance company may require you to use its verification portal. A specialty vendor may only accept orders through a clunky ecommerce site. Or a marketplace may be where all of the demand for your product or service lives.

You can build a better internal tool, but you still have to use those sites.

The browser is the integration point

Chrome extensions have always been a way to change the experience of a site you do not control. An extension can read information from a page, add controls to it, and help guide a user through a workflow.

Historically, that was possible but often not practical. You needed to write and maintain custom code for every awkward workflow, and the payoff had to be large enough to justify it.

The latest AI models change that calculation. It is now much easier to build an extension that augments a legacy site, whether that means changing a workflow, extracting information from a page, or adding LLM capabilities directly where people are already working.

Instead of asking someone to copy information from one system into another, you can put the assistance in the browser tab where the work already happens.

A bike search on Facebook Marketplace

I recently had a good excuse to try this out. I was looking for a bike on Facebook Marketplace with a specific set of requirements. The hard part was not finding listings. It was reviewing the photos for each listing to determine whether a bike was actually a fit.

Doing that manually meant opening and reviewing dozens of listings every day. That is exactly the sort of repetitive visual task that an AI model can help with.

So I built a Chrome extension that uses OpenAI to review listing photos and flag the listings that match what I was looking for. Rather than replacing Facebook Marketplace, the extension improves the part of the Marketplace workflow that was taking the most time.

The result is not a fully autonomous bike buyer. It is a faster way to narrow down a large list of listings so I can spend my time looking at the promising ones.

Where this approach works

The Marketplace example is personal, but the pattern applies to business workflows too. Look for web-based processes where a person repeatedly has to review, classify, summarize, or move information before they can make a decision.

A Chrome extension can be a practical place to add help to:

  • an insurer’s required portal
  • a vendor ordering site
  • a marketplace your team depends on
  • an internal legacy application that is difficult to change

The goal is not necessarily to replace the site. It is to remove the tedious steps around it while keeping people in the workflow they already need to use.

See it in action

Check out the demo below to see the bike finder at work:

Watch the video on YouTube

Interested in building something similar for a workflow your team cannot avoid? Get in touch with Setfive.

Sherpa by Setfive: A simple way to find the work your team should not be doing

Inside most companies right now, AI is already at work. Even if you have not rolled out ChatGPT Team or Copilot, people are using their personal subscriptions to speed things up. That is great for initiative, not so great for consistency. It looks a lot like the early Excel era: clever workarounds, duplicate effort, and new questions about data governance.

Sherpa is our way to bring order to that energy. We analyze real tasks from Asana or monday.com, group similar work with an LLM, and point to the places where automation will pay off. You get a clear plan you can act on, without buying another stack of licenses first.

What Sherpa is

Think of Sherpa as an AI audit for your task data. It connects to your workspace, reads tasks with your permission, and maps the repetitive patterns that eat time. Then it scores where automation is likely to win, explains why, and recommends how to build it. The output is practical and specific: plays, tools, prompts, and an effort estimate so you can prioritize.

How it works

You start by connecting Asana or monday.com with OAuth. Access is read only and under your control at all times. We do not change or write tasks.

Next, a large language model groups related work and finds recurring patterns. That includes obvious repeats, quiet duplicates that happen across teams, and tasks that often move together in a process.

Finally, we deliver a short report that tells you what to automate, in what order, and how. Each recommendation includes expected time savings, suggested connectors or integrations, and sample prompts so your team can move quickly.

Typical turnaround is about a week from connection to findings.

Why scan tasks now

Personal AI usage is already shaping how work gets done. Sherpa helps you see what is working, what is risky, and what should be standardized. It replaces guesswork with a picture of real workflows, so you can invest in the right automations and avoid paying for licenses that will not get used.

Leaders also get a common view of where hours are going. That makes process conversations easier. Instead of debating tools in the abstract, you can point to specific clusters of tasks and decide how to fix them.

What you get in the report

  • An automation scorecard with high, medium, and low opportunities, each with a short rationale.
  • A top 3 list of automation plays with exact steps, recommended tools, and integration notes.
  • An impact section that translates hours into dollars using your inputs.

You also get a recurring task map, duplicate detection across teams, suggested prompts and connectors, and a next step build plan that you can implement with your team or with Setfive.

A sample finding

Manual reporting shows up in almost every audit. A team exports CSVs every Friday, merges them by hand, and posts a summary. The play is straightforward: schedule the extract, load it to a source of truth, and send a templated summary to Slack or email.

  • Impact: High
  • Effort: Medium
  • Estimated savings: 6 hours per week

If 10 people each save 6 hours per week at an average loaded rate of 75 dollars per hour, that is 6×10×75=4500 dollars of capacity back every week.

Where Sherpa fits with ChatGPT Team and Copilot

Already have licenses? Sherpa shows where to deploy them and turns ad hoc prompts into repeatable, auditable workflows.

Still evaluating? Run Sherpa first to find the highest value use cases, then buy only what you need.

Not ready to buy seats? Many plays use tools you already have, so you can capture savings now and expand later.

Security and privacy

Sherpa uses OAuth with scoped, read only access. You can revoke access at any time. We follow your data retention requirements, and your findings are your IP. We do not use your data to train public models.

Who benefits

Ops and RevOps leaders with checklist heavy processes. PMOs juggling handoffs. CS and Support teams producing weekly reports. Marketing ops moving content through approvals. Finance and People teams closing the loop on routine reconciliations. If the same task shows up again and again, Sherpa will find it.

FAQs

Do we need to change how we work to try it? No. Sherpa analyzes the work you already do.

Will this replace people? The goal is to remove low leverage, repetitive tasks so your team can focus on higher value work.

Can you help implement the plays? Yes. Implementation projects are scoped after the audit.

Try the Free AI Task Audit

Stop guessing where AI will help. Measure it. Sherpa shows you the work your team should not be doing and how to automate it, fast.

Get your Free AI Task Audit, a concise scorecard, and a prioritized plan with savings you can defend.
Ready to see your opportunities? Get in touch at contact@setfive.com or read more about Sherpa at sherpa.setfive.com

Gathering Structured Data From Phone Calls

A lot of information these days is just a Google search away, but there is still a surprising number of businesses out there that keep information like pricing locked behind phone lines. Oftentimes, this is deliberate, and they may do this for a variety of reasons:

  • Fluctuating prices that change based on demand, inventory, or seasonality.
  • Sales psychology that converts curious callers into customers.
  • A competitive advantage in keeping pricing opaque to competitors.
  • Personalized quotes that change based on customer need.
  • Old school businesses that just never went digital.

Traditionally, to gather information from these businesses, you would need someone or even multiple people to work through an endless call list, navigating phone menu trees, waiting on hold, and manually transcribing conversations into spreadsheets. This is tedious, expensive, slow, and doesn't scale.

At Setfive, we decided to look into how we could automate this.

OpenAI Realtime API

The timing couldn't have been better. As we were exploring ways to do this, OpenAI released its Realtime API, a game-changer for voice-based AI applications. Unlike conventional text-based APIs that require separate speed-to-text and text-to-speech steps, the Realtime API combines these and enables:

  • Low-latency native voice conversations.
  • Natural interruptions for more human-like interactions.
  • Built-in function calling for triggering actions mid-conversation.

This was an AI capable of having an actual over-the-phone conversation.

Building The Bridge

With the brain of the operation sorted, it was time to find a way to actually make phone calls. For this, we chose Twilio, a well-regarded platform for telecommunications for almost two decades.

Twilio's Media Streams API made it simple to pipe audio directly to and from the OpenAI Realtime API, creating a seamless conversation flow. The business on the other end hears a responsive customer who can handle unexpected conversational turns.

Navigating The Maze

One of the first challenges we ran into? Phone trees. You know them: "Press 1 for appointments, Press 2 to speak to a customer service representative, …" These interactive voice response (IVR) systems are designed for touch-tone input, not voice commands.

We solved this by building AI tools that can simulate DTMF (Dual-Tone Multi-Frequency) signals using Twilio's API - which required some trial and error with their callback and TwiML architecture - so that our AI can listen to menu options, simulate button presses, navigate complex multi-level menus, and find the fastest path to reach a customer service representative or a front desk.

From Conversations To Structured Data

Getting through to the right person is only half the battle. The real magic happens when our AI finally gets into a conversation. From there, we are able to extract structured information from free-flowing conversations in real time. Using carefully crafted prompts, our system can:

  • Identify key information even when it's mentioned casually
  • Ask clarifying questions about discrepancies in the information received
  • Extract additional valuable data like availability, pricing details (first-time customer, minimum orders, ect.), and more
  • Create clean, structured data ready for your database, Excel spreadsheet, or whatever else you're using.

When Nobody Answers

Here's something we didn't anticipate: businesses that rely heavily on phone communication are often too busy to answer their phones. These are often small businesses that may not have dedicated staff for handling phones or may have employees who wear multiple hats. They're not sitting by the phone waiting for calls.

This was having a real effect on our success rate, and we didn't want to make multiple calls to the same business, hoping for someone to be available. The next step was obvious: voicemail. We enhanced our system to handle a full communication cycle:

  • Intelligent voicemail detection to detect when we have reached a voicemail inbox.
  • Leave a natural message requesting whatever information the AI is looking for.
  • Callback handling that is able to naturally continue the conversation when a business calls back.

Ready to Build?

Interested in how this can help you? Email us at contact@setfive.com to find out more or check out
our demo at voice2data.setfive.com!

web3: Creating a NFT contract

Wow...it's been awhile!

A couple of weeks ago one of our clients approached us about helping them build an NFT (more on that later). In case you're not "extremely online" and don't know what web3 or NFTs are here's a quick primer.

Crypto and NFTs

As crypto currencies go Bitcoin and Ethereum are the "OG" coins. They're related projects but ultimately quite different. Ethereum differentiates itself because it enables the Ethereum Virtual Machine which is a global, distributed computing environment which uses Ethereum as payment for executing computation. Executing pieces of code, known as smart contracts, on the EVM is broadly referred to as "web3". The web3 vision is that it should be possible to transition dozens of financial businesses processes onto the blockchain by using the EVM and smart contracts to encode the rules of the processes. Think stuff like insurance, stock issuance, and even sports books.

Non-fungible tokens (NFTs) are a specific type of smart contract which encode ownership of an asset onto the Ethereum blockchain. What makes NFTs special is that because of the decentralized nature of the blockchain and the EVM its possible to freely trade NFTs and encode rules into their smart contracts. OpenSea is the defacto NFT marketplace where users can trade tokens without the original creators having to create any additional infrastructure. It's like StubHub...but anyone can sell any NFT on it and anyone can access it.

In addition, because the EVM is Turing complete its possible to enable extremely complex behaviors within the contract of an NFT. In theory, a NFT could represent ownership of any items from tickets to an event or digital collectables. But as it turns out, digital collectibles is where most of the action is today. See for example Bored Ape Yacht Club which has seen some tokens trade for upwards of $24m, Set of "Bored Ape" NFTs sells for $24.4 mln in Sotheby's online auction

OK, now that we're all caught up how does one create an NFT? There's more or less 3 steps:

  1. Develop a smart contract in Solidity which implements the EIP-721: Non-Fungible Token Standard
  2. Write some HTML/JS to interact with web3 via MetaMask to call your contract
  3. Publish the contract to the Ethereum blockchain
  4. Mint your tokens via the HTML/JS from step 2

Sounds simple enough, but how do you actually make it happen?

Here's a walk through to launch a NFT in your local test environment.

You can develop the Solidity code in any text editor. But there are some IDE options including an IntelliJ plugin and a larger list here, https://ethereum.org/en/developers/docs/ides/ It's certainly possible to write a EIP721 Solidity contract from scratch but you'll end up writing a lot of boilerplate code which will increase the surface area for bugs. A sensible alternative is to use the OpenZeppelin framework which provides you with a suite of battle tested, open source libraries to bootstrap your smart contract. Additionally, OpenZeppelin has a handful of working tutorials so that you can see a smart contract working end to end. Check out OpenSea Creatures.

After you have your contract the next piece is interacting with the blockchain to publish your contract. There's a few tools here that all interact:

  1. MetaMask - MetaMask is a browser based crypto wallet and web3 provider. It allows you to store Ethereum and interact with contracts on the Ethereum blockchain. You'll use MetaMask to ultimately mint a token.
  2. Ganache - Ganache is a tool which allows you to run an Ethereum blockchain on your local machine
  3. Truffle - Truffle is a suite of tools which makes it easier to interact with the blockchain. You'll use Truffle to publish your contract and invoke methods within your contract.

Once you have all the tooling setup the steps you'll need to take are:

  1. Setup MetaMask and note the mnemonic phrase which your keys were initialized with
  2. Launch ganache with that mnemonic so that your accounts have some Ethereum
  3. Use Truffle to publish your contract to your local ganache blockchain
  4. Use the HTML/JS integration you wrote to invoke MetaMask to call the .mint() function in your contract

Congratulations, you just minted your first NFT in test!

The process for deploying a NFT live is effectively the same except that you'd need to buy some real Ethereum and you'd point Truffle at the live network when you publish your contract.

Hope this was helpful and we'll add more web3 related content as we continue to build solutions on it!