Back to News & Insights
Web Development September 9, 2026 · 10 min read

My OSS Projects: AngleSharp

This is the first post in a new series, "My Open-Source Projects", where I go through some of the...

My OSS Projects: AngleSharp

This is the first post in a new series, "My Open-Source Projects", where I go through some of the OSS projects I started or maintain and tell you the story behind them - the good, the bad, and the "why did I think this was a good idea at 30,000 feet" parts. First up: AngleSharp.

Before the story, the pitch: AngleSharp is a .NET library that parses HTML, SVG, MathML, CSS, and (to a good extent) XML, and gives you back a fully-featured, spec-conformant DOM. Not "DOM-ish." Not "good enough for scraping." The actual W3C DOM API, the same querySelector, querySelectorAll, and element interfaces you already know from the browser console - except it's C#, it runs headless, and there's no browser in sight.

If you've ever reached for a regex to parse HTML: please don't. You know why. AngleSharp exists so that nobody has to write ]> ever again.

Once upon a time, I had what I thought was a brilliant idea: build a cross-platform GUI toolkit using HTML, CSS, and C#. I was certainly not the first person to think of this - plenty of people had similar thoughts before me - but back then it was still a fairly fresh take.

The more I thought it through, though, the more obvious it became: you can't just take HTML and CSS and strip them down to "the easy 80%". If you want this to actually work, you need the real deal - a proper HTML parser, a proper CSS engine, the whole circus. No shortcuts.

So naturally, the reasonable thing to do was to just... write an HTML5 parser. From scratch. In C#. Sure, why not.

In 2013 I was flying to the Microsoft MVP Summit, and for reasons that made complete sense to me at the time, I brought a printed copy of the HTML5 spec with me. Not a novel. Not a magazine. The spec.

I started coding on the plane. By the time we landed, the parser was already "working" - in the sense that the happy paths worked. Feed it well-formed markup and it would dutifully produce a DOM. Great success, right?

Well, that's roughly the point where I discovered the dirty little secret of the HTML5 spec: it's massive not because HTML is a complicated language, but because of everything around it - error handling, edge cases, and the glorious pile of "what should happen when the markup is garbage" scenarios that browsers have been quietly agreeing on for decades. Turns out the "happy path" is maybe 20% of the actual spec. The other 80% is browsers being incredibly forgiving about human mistakes.

I kept grinding away at it, and eventually most of the edge cases and tests turned green. And then, like clockwork, I hit the point every side project hits: frustration, a pause, and a "why am I doing this to myself" moment. Every maintainer knows this phase. It has no official name, but "why did I do this to myself" captures it well enough.

Eventually I picked it back up with a very simple thought: before this thing quietly dies in a local folder, let's write a CodeProject article about it and push the code to GitHub.

I already had some open-source experience at that point - mostly as a contributor. The one project I actually maintained was YAMP, and thanks to some very patient people with a lot more GitHub experience than me, I'd picked up a few things about "doing OSS properly."

When I woke up, something had clearly happened. The repository already had 120+ stars, and the article was ranking surprisingly well. Nothing makes you suddenly very motivated about a side project like waking up to numbers you didn't expect.

For a while, most of the effort went into the internals - making the parsing actually correct, not just "correct enough." Once that settled down, the API itself went through some pretty massive changes. Not always changes that users loved, if I'm honest. Breaking changes are never fun to be on the receiving end of, and I was on the giving end a fair bit during this period.

The big turning point was AngleSharp 0.10. This release quietly laid the groundwork for what would define AngleSharp going forward: modularity. Suddenly you could just add another library and your document could parse JavaScript. Add another one and you got CSS. This came from a lightweight-but-surprisingly-capable dependency injection system and a service-based configuration approach that let you chain extensions together like Lego bricks.

For years, I genuinely wasn't sure I could call the API "stable" and commit to semver. Not because it was shaky - it just felt like a big commitment. Eventually, after years of the API being de facto stable (even if I hadn't officially blessed it as such), I released 1.0.

From that point on, my main driver hasn't been "let's avoid a 2.0 or 3.0 forever." I have nothing against major version bumps. My actual rule is simpler: a breaking change needs to earn its place. If it's not genuinely useful enough to justify the pain it causes downstream, it doesn't happen.

I've told this story mostly in first person so far, which is a bit unfair, because AngleSharp would have died somewhere around "some happy paths seemed to work" if it had stayed a one-person effort.

Want to discuss this further?

Book a free strategy call with our team to see how these insights apply to your specific business goals.

Book a consultation