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

Ventura + Keyboard Maestro + iCalBuddy = Confusion

  • Mike
  • November 17, 2022

Early this year I setup a bunch of calendar related automations with my Macs, Keyboard Maestro, and the iCalBuddy script and they’ve been very successful. I have a button on my Steam Deck that shows when my next meeting is, and I have serval automations triggered when I’m currently in a meeting such as turning on a red light outside of my home office door.

Read more

Virtual Influencers - From Cartoons to Deep Fakes

  • Mike
  • October 11, 2022

Studio71 Germany has recently launched not one but two virtual influencers and they’ve done a great job with the implementation and marketing around this project (disclosure: I am the global CTO of Studio71). I’ve been thinking about it a lot and on the one hand this idea of a “fake” or “virtual” influencers comes and goes over the years and every time it comes back we all like to pretend that it’s a crazy idea.

Read more

The Story of My Slightly Funny Coolio Joke

  • Mike
  • September 29, 2022

Coolio, the rapper who absolutely slayed the 90s, sadly died today at the age of 59. Coolio, the West Coast rapper whose gritty music and anthemic hits like “Gangsta’s Paradise” helped define hip-hop in the 1990s, died on Wednesday in Los Angeles. He was 59. His longtime manager, Jarez Posey, confirmed his death.

Read more