Featured image of post I Had to Write a Script to Submit My Medical Claims to Cigna

I Had to Write a Script to Submit My Medical Claims to Cigna

A deep dive into automating Cigna's claims portal with AI and browser automation, and how the technical struggles revealed accessibility failures that likely violate federal law. The friction is not accidental but a predictable outcome of a system designed to maximize profit at the expense of patient care.

I just spent over an hour building a browser automation script to submit 12 medical claims to Cigna. Standard CMS-1500 superbills from my doctors, the kind that every medical office generates, with every required field filled in. The fact that I needed to write code to do this tells you everything about how health insurance works in America.

Why None of My Doctors Take Cigna

Before we get to the technical absurdity, some context. I see several doctors, and not a single one of them accepts Cigna as an in-network insurance provider. The reason is straightforward: Cigna routinely denies claims and makes it extremely difficult for providers to get paid. Doctors’ offices have limited administrative bandwidth. When an insurer consistently rejects or underpays claims, providers stop accepting that insurance. The result is that I pay out of pocket and submit superbills myself for reimbursement.

This is not a bug in the system. It is the system working exactly as designed.

The Quiet Logic of Making Things Difficult

The Cigna Group is a publicly traded, for-profit C corporation. It trades on the NYSE under the ticker symbol CI. In 2025, it reported $275 billion in revenue, $6 billion in net income, and returned over $5 billion to shareholders through dividends and share buybacks. Its board has a fiduciary duty to shareholders, and executive compensation is tied to financial performance.

For a health insurer, the math is quite simple. Revenue comes from premiums. Costs come from paying claims. Every dollar paid out for someone’s medical care is a dollar that does not flow to the bottom line. The company is structurally incentivized to collect as much as possible in premiums while paying out as little as possible in claims.

This is not speculation. In 2023, ProPublica reported that Cigna uses an algorithm called PxDx that allows its doctors to deny claims in bulk without ever opening a patient’s file. In two months in 2022, Cigna doctors rejected over 300,000 claims using this system, spending an average of 1.2 seconds per case. One doctor denied 60,000 claims in a single month. A class action lawsuit followed, and a federal judge allowed it to proceed in March 2025.

So when the claims submission process is burdensome, when the website throws up confusing error messages, when the OCR system claims it cannot find a date of service that is clearly printed on the form, you have to ask yourself: is this incompetence, or is this working as intended?

I am not saying there is a meeting at Cigna headquarters where someone decides to make the submit button harder to click. But when the incentive structure rewards friction and the result is friction, the distinction between intentional and incidental does not matter much to the person sitting at their computer trying to get reimbursed for medical care they already paid for.

Countries with non-profit or single-payer health systems achieve better population health outcomes at lower per-capita cost. The administrative function of pooling risk and processing payments does not require a for-profit corporation extracting billions in profit. What Cigna uniquely adds to the equation is the profit motive and everything that comes with it: the algorithmic claim denials, the shareholder returns, and also a claims portal that makes submitting a simple form feel like an obstacle course.

What It Actually Takes to Submit a Claim

Cigna’s online claims portal lives at my.cigna.com. Here is what the process looks like for a single claim.

You need an itemized bill with eight specific pieces of information: provider name and address, tax ID or NPI, patient name, date of service, diagnosis code, procedure code, billed amount, and place of service. A standard CMS-1500 superbill contains all of this by definition. That is precisely what the form is for.

You upload the scanned superbill, then answer five yes/no questions about auto accidents, work injuries, Medicare, and other coverage. You select who should receive payment. You certify the information is accurate, name your claim, and submit.

Sounds simple enough for a single claim. But I had 12 superbills sitting in a pile. At three to five minutes each, manually working through the portal’s multi-step wizard, that is 35 to 60 minutes of clicking, waiting, and dismissing warnings.

And then there are the warnings.

After you upload a properly formatted CMS-1500 superbill and select a patient, Cigna runs OCR on your document and shows a spinner that says “Checking documents for required information.” This process takes anywhere from 5 to 30 seconds. Then it pops up a modal warning you that it could not find the date of service, or the billed amount, or both.

The information is right there on the form. Printed in the standard boxes. Eleven of my 12 superbills triggered this warning. Only one went through without complaint. The portal warns you that “without this information, your claim will require additional processing and is less likely to be approved.” It then gives you two options: a prominent blue button to upload more documents, and a small text link to submit anyway.

Think about that from an accessibility perspective. If you are visually impaired, have limited mobility, or struggle with technology, this process is a nightmare. The warnings are misleading. The UI pushes you toward uploading more documents you do not need to upload. And you have to do this for every single claim.

Automating the Nightmare

I decided to automate the process using Claude Code connected to Chrome through the Chrome DevTools Protocol (CDP). The idea was simple: log in once, and let the script handle the rest of the submission workflow for each of my 12 superbills.

It was not simple.

Cigna’s portal is built with Angular and uses a web component library called “Leaf.” Every interactive element, every button, dropdown, checkbox, and modal, is wrapped in Shadow DOM. If you are not a web developer, Shadow DOM is a browser feature that encapsulates a component’s internal structure, making it invisible to normal selectors and automation tools. It is a perfectly legitimate technology for building component libraries. It is also a significant barrier to any kind of browser automation.

Standard approaches to clicking a button do not work. You cannot just say “click the submit button” because the actual HTML button element is hidden inside a shadow root, nested inside a custom element. You have to pierce through the shadow boundary: find the custom element, access its shadow root, then find the real button inside. For the warning modals, the nesting goes even deeper: a shadow DOM inside a dialog inside slotted content inside another shadow DOM containing the actual button.

The patient selection dropdown was the single hardest element to automate. Programmatically setting the value and dispatching change events did not trigger Angular’s change detection. The framework simply ignored it. The solution was to physically simulate mouse clicks and keyboard navigation: click at the exact pixel coordinates of the dropdown, press arrow keys to navigate to the right option, then press Enter. Even that was fragile because the number of arrow key presses needed was not always consistent. When I described the problem to Claude Code, it added a verification loop: select via keyboard, read back the selected value, retry if wrong.

After upload, Cigna runs server-side validation that takes 10 to 30 seconds with no completion callback. You just have to poll the page until the text “Upload complete” appears. And the order in which you fill out the form matters: if you select the patient before filling in the other fields, the document checking process can reset some of your answers. The correct order, learned through trial and error, is to upload the file first, wait for validation, and then fill in the rest of the fields.

The development process required 20 separate helper scripts, each addressing a single sub-problem: clicking a specific button type, inspecting a modal, fixing the dropdown, finding element coordinates. Every script had to be tested against the live site with real session state. And Cigna’s portal silently timed out the session mid-batch with no warning, requiring a fresh login and restart.

The Code Is Not Just Hostile to Bots. It Is Hostile to Humans.

I briefly wondered whether automating Cigna’s portal violated their terms of service. That concern led me to examine the page’s ARIA attributes, the metadata that makes web pages usable for people with screen readers and other assistive technologies. What I found was pretty bad.

The patient dropdown, the single hardest element for my script to automate, has no accessible label. No aria-label, no <label for> element. It is a raw dropdown that a sighted user can figure out from visual context, but a blind user interacting through a screen reader has no way to know what the field is asking for. The reason my script could not find it programmatically is the same reason a screen reader cannot identify it: the code is semantically hollow.

It gets worse. Steps 4, 5, and 6 of the claims wizard all announce themselves to screen readers as “Step 1: Get a bill from your provider.” This is not a complex architectural decision. This looks like a copy-paste error. A developer duplicated the Step 1 code block, pasted it for the remaining steps, and never updated the text. If anyone had tested this page with VoiceOver even once, they would have immediately heard the same step announced three times in a row.

The validation spinner and warning modals that caused so much trouble for my automation are also invisible to screen readers. They lack aria-live regions, which means when Cigna’s system pops up a warning saying it cannot find the date of service on your superbill, a blind user gets no notification at all. The error appears silently. The user has no idea anything happened and no way to dismiss a modal they do not know exists.

Here is the thing that matters: the Leaf component library that Cigna uses actually handles its own elements correctly. The radio buttons and checkboxes have proper IDs and shadow DOM wiring. The library works. The failures are all page-level implementation errors by Cigna’s developers. This is not a case of complex enterprise architecture creating unavoidable trade-offs. This is negligent coding that was never tested with assistive technology.

Since Cigna administers Medicare Advantage plans and receives federal funds, they are subject to Section 508 of the Rehabilitation Act and the Americans with Disabilities Act. These are not minor cosmetic issues. They are functional blockers. A blind user cannot independently complete the claims submission form because they cannot identify the patient field, cannot hear the error messages, and cannot navigate a wizard whose steps are mislabeled. The portal seems to effectively bar users with disabilities from submitting claims they are legally entitled to file.

AI Made This Possible

Five years ago, this automation project would have been impractical for a single person dealing with 12 claims. The Shadow DOM piercing, the fragile dropdown simulation, the timing-dependent form filling, all of these problems are solvable, but the debugging time for each one would have been prohibitive for such a minor task.

Claude Code changed the equation. I could describe what I was seeing on the screen, paste error messages, and work iteratively through each obstacle. When the dropdown ignored programmatic value changes, I could explain the symptom and get suggestions for alternative approaches. When the modal buttons were invisible to standard click methods, we tried shadow root traversal strategies. The AI did not magically solve everything on the first try, but it compressed what would have been days of Stack Overflow searches and trial-and-error into about an hour of collaborative debugging. Ironically, the AI could navigate the site better than a human screen reader user could, simply because it could see the raw HTML that the accessibility tools were blocked from reading.

The combination of an AI coding assistant and browser automation through CDP means that hostile web interfaces are no longer an impenetrable barrier. If you can describe what you are trying to do and what is going wrong, you can build automation for it, even when the target application seems designed to resist exactly that.

The Bigger Picture

I have a PhD in computer science and 25 years of experience in software engineering. I used an AI coding assistant, a browser automation framework, and 20 custom scripts to submit 12 standard medical forms. The process took a little over an hour to develop, roughly the same time it would have taken to submit the claims manually. But that was not the point. The scripts are reusable. The next time I have a stack of superbills, I log in and run the script. The manual process starts over from scratch every time.

What does someone without these tools do? What about the elderly patient who is not comfortable with technology? The working parent who does not have an hour to spend fighting with a website? And as the ARIA audit shows, a blind user may not be able to complete this form at all.

They do one of two things: they spend an hour doing it manually and make mistakes leading to denials. Or they give up and do not submit claims they are entitled to. Both outcomes benefit Cigna’s bottom line.

The claims submission process is a small window into a much larger problem. When a for-profit corporation sits between patients and their healthcare, every point of friction becomes a potential profit center. The hard-to-navigate website, the OCR that cannot read standard forms, the misleading warnings, the session timeouts, none of these are technical problems that a $275 billion company cannot solve. They are choices, made in an environment where the financial incentive points away from making things easy for the people submitting claims.

As I write this, my script is painstakingly submitting each superbill, clicking through shadow DOM elements and dismissing warnings about missing information that is clearly present on every form. It will take about 18 minutes for all 12 claims. The manual alternative would have taken an hour.

A cynic would say this is an evil system. Not broken, not inefficient, but evil. A system designed to squeeze more and more money out of people who are sick, scared, and desperate for help. A system where a company posts $6 billion in profit and $5 billion in shareholder returns while its website cannot read a standard medical form and blocks the blind from using it entirely. A system where an algorithm denies 300,000 claims in two months while doctors rubber-stamp the rejections at 1.2 seconds each. A system that bets on the fact that most people will not fight back, will not appeal, will just pay the bill and move on.

The views expressed on these pages are my own and do not represent the views of anyone else.
Built with Hugo - Theme Stack designed by Jimmy