Hacking the STLToday Paywall v2022

  • Mike
  • April 19, 2022

Here we are again.

STLToday, the website for my hometown newspaper the St. Louis Post Dispatch, has updated their paywall and, as is tradition, it’s time to take a look, see what they did, and offer suggestions so they can make it better. In short, let’s hack the STLToday paywall.

But first, let’s review how we got here.

In 2014, while trying to read an article I noticed that STLToday had turned on a paywall. I hacked it so I could read the article, told everyone, and then it got picked up by the St. Louis media.

In 2019 the STLToday team updated the paywall and it was still easily cracked by yours truly by a bookmarklet. I offered suggestions for improvement, but it was not taken.

Cut to 2022 and they have updated the paywall logic yet again. Did they improve it? Did they finally make something that actually prevents someone from working around it? Will they ever take my suggestions? Let’s break it down!

Here’s the good news: The 2022 version is an improvement! The bad news is that it’s still very crackable.

The 2022 version starts off strong by putting their code nice and high in the logic, they have encoded their meta tags, and if the user is to be blocked, they actually delete the content from the page rather than just hiding it with CSS styles.

The basic logic is that they setup a bunch of global variables (more on that later) and then call TNCMS.Access.checkAccess with a callback function. That function checks the response and either shows the user a soft paywall with a request to sign up, or a hard paywall that says you must signup and removes the article from the page.

Right away, there are two clear methods to get around this paywall:

  1. Get that checkAccess callback function to return the soft paywall every time.
  2. Rename the article text blocks so they aren’t deleted by the code.

But wait! Before we do that we have deal with the easy stuff first, such as hiding the annoying modal nag screens, and deciding how we will launch the code. In the previous version we used a bookmarklet because they are easy to use, but now that they are finally running the paywall logic right away, and deleting the article we have to inject our code earlier. The only way to do that is with a browser extension, which is a slight bummer as it’s more work and harder to distribute than the bookmarklet, but good for Lee Publishing for making improvements! The overlays however we unchanged and hiding them is just a matter of removing a view divs and fixing the overflow style.

Ok, let’s get in to it!

Get that checkAccess callback function to return the soft paywall every time.

What is their obsession with global variables? We may never know but I went ahead and set a couple of them to true in the hopes that we can trigger this block and force the “soft” paywall.

if(oResp.required || window.show_dimissable_registration){
	if(window.show_dimissable_registration) { 
    	sCase = 'user registration';

	case 'user registration':
		__tnt.log('LEE: load regwall');
		window.lee_regwall_loaded = true;
		} else {

I also wrote a function that waits for their TNCMS object to appear and then overrides the checkAccess function to be one that just returns the same soft paywall response every time:

window.lee_meter_loaded = true;
window.show_dimissable_registration = true;

function defuse() {
  if(window.TNCMS && window.TNCMS.Access) {
    window.TNCMS.Access.checkAccess = function(fnSuccess, fnFailure) {
      fnSuccess({required: false});
  } else {
    setTimeout(defuse, 10);


That seems to do the trick and then you actually don’t need the #2 solution at all…but let’s review it anyway.

Rename the article text blocks so they aren’t deleted by the code.

Later on in their logic, when the “hard” paywall is drawn the following happens:

$("#asset-content .lee-article-text:not('.first-p')").html('');
$("#asset-content .inline-asset").html('');
$("#asset-content .lee-article-text.first-p").append('<p><strong>Please subscribe to continue reading&hellip;</strong></p>');

What that is doing is grabbing every paragraph of article text, except the first paragraph, and setting it to blank. If you could get your code to run first you could easily drop this by just renaming the .lee-article-text paragraphs to something different, like…hmmm, I don’t know…maybe .free-article-text!

function evade() {
  let oldClass = "lee-article-text";
  let newClass = "free-article-text";

  var divs = document.querySelectorAll('.lee-article-text');
  if(divs.length > 0) {
    for(i = 0; i < divs.length; ++i) {
  } else {
    setTimeout(evade, 10);

…and there you have it.

So, let’s review.

What they did right:

  1. Made sure the paywall code started faster.
  2. They removed the content rather than just hiding it.
  3. They obscured their metatags.

What they did wrong:

  1. They still send the content to the browser by default and then delete it later.
  2. They could have worked a little harder on identifying which content blocks to delete.

This is the biggest step forward we’ve seen from the STLToday paywall. Will it stop anyone with knowledge of javascript and 30 minutes of free time it takes to create a browser extension? No, but honestly, there aren’t that many of us. I commend them for at least improving it to the point where they aren’t defeated by a lowly bookmarklet any more!

You can see my full source code and quick descriptions of how to run the code on GitHub: https://github.com/mikeflynn/stltoday-paywall-buster

If you have any questions or comments, fire away on Twitter @thatmikeflynn, and go Cardinals!

Related Posts

An Office Tour in Pieces

  • Mike
  • August 27, 2023

I’ve been experimenting as a TikTok (and YouTube Shorts) creator. Let me explain. I recently shot a home office tour (thanks to my daughter Molly who was my camera operator) but when I started to edit it I just didn’t love it. I might still release it, but what I was inspired to do instead was to make a bunch of little videos showing off one specific thing in my office rather than a long video going over everything at a high level.

Read more

I Made an Arcade Cabinet

As a kid in the 80s and 90s there were a few things that you could see in a friend’s house that would immediately impress you. Examples would be, a second fridge, usually in the garage, one of those big projection TVs, or, and this is the big one, a full stand-up arcade cabinet.

Read more

AI Headshots Sorta Work

  • Mike
  • April 13, 2023

I gave AI headshots a try and it’s not bad. Some are quite good, but I’d call it a 7/10 over all. I made and attached a grid of the results, but I mixed in one real picture. Any guesses? The hardest part was that it required 10-20 selfies with different backgrounds and outfits, but since I don’t take a lot of selfies I had to run around my house finding backgrounds and changing clothes for 30 minutes to generate enough training data!

Read more