Method
143,126 em dashes, 80,913 posts, 59.7M words. Everything here is derived from one committed snapshot; nothing is fetched when you load a page.
What counts
- An em dash is one U+2014 character. En dashes and hyphens are counted separately and never mixed in.
- Only body prose counts. Code blocks, tables, navigation, newsletter boxes and related-post lists are stripped before counting, so a shell flag or a repeated sidebar never inflates a total.
- Posts under 60 words are dropped as stubs, changelog fragments or failed extractions. The floor has a cost worth naming: a blog that posts mostly short notices is measured on its longer pieces, so its rate reflects the writing it does at length rather than everything it publishes.
- Translated copies are excluded. They duplicate an English original and every language punctuates differently.
- A post is placed in the month it was published, in UTC, taken from the page's own structured metadata where it has any, then the date in its URL, then the first date in its visible text.
How rates are calculated
- Every rate divides summed em dashes by summed words or posts over a window. Averaging monthly ratios would give a month with two posts the same weight as a month with sixty.
- The two comparison windows are 2018-01 to 2022-11 and 2024-01 onward. 2023 sits in neither: it is the transition year, and putting it in either window flatters that side of the argument.
- A change figure is only quoted when the earlier window holds at least 25 posts carrying at least 10 em dashes between them. A multiplier divides by the baseline, so a blog that barely existed then produces an enormous and meaningless number: one baseline of 11 posts and 2 em dashes rendered as a 38-fold rise. Blogs below the floor show a dash in the change column rather than a figure.
- Charts plot a 12-month trailing window. Monthly rates on a blog publishing a handful of posts are mostly noise; the raw months are in each blog's own table.
- Months with no posts are gaps, not zeros. A line breaks rather than diving to the floor.
- A window holding fewer than 2,000 words is left blank rather than plotted. A ratio over a tiny denominator is noise wearing a number's clothes: one 132-word post carrying four em dashes reads as 30 per 1,000, which is not a fact about how that blog writes.
Which measure to believe
The three measures answer different questions and they do not always agree. Em dashesper post is what a reader actually meets, but it rises when posts get longer as well as when punctuation changes. Across this corpus the average post grew from roughly 360 words in 2008 to about 1,170 today, and over that same span the per-post figure more than tripled while the per-1,000-word density did not move at all. The long climb on a per-post chart before about 2018 is mostly posts getting longer.
From 2018 onward, where typical length is close to steady, the two agree: per post is up about 1.9 times and per 1,000 words about 1.7 times. That is the part of the change that length does not explain. Per 1,000 words is what the ranking sorts by, for that reason.
The other three measures
A rise in one punctuation mark is thin evidence by itself, so three other things are counted over the same text. None of them detects anything, and none is offered as proof of authorship.
- Words per post is the plainest of the three, and it moves for ordinary reasons as well as interesting ones: a blog that starts publishing tutorials instead of release notes gets longer without anyone changing how they write.
- Sentence variation is the coefficient of variation of sentence length, standard deviation over mean. Human prose is bursty, a four-word sentence next to a forty-word one, so a falling line means sentences are converging on a single length. Runs longer than 80 words are discarded first: stripping markup leaves headings and list items running together with no full stop between them, and because variance squares the distance from the mean, a handful of those artefacts would otherwise decide the answer.
- Marker words counts a deliberately narrow list that was rare in this corpus before 2023 — delve, tapestry, myriad, intricate, plethora, burgeoning and a few dozen more, plus phrases like “ever-evolving”. The obvious candidates are missing on purpose: robust, leverage, comprehensive and streamline have been ordinary technology-blog vocabulary for twenty years, and counting them would measure the genre rather than any change in it.
Every stored figure has to survive being summed, because months are added together into windows. That rules out anything shaped like a per-post average, which is why sentence length is kept as a count, a sum and a sum of squares rather than a mean, and why measures like lexical diversity are absent: they cannot be added up, and a version that looked additive would have been quietly wrong.
The corpus changes, not just the writing
The blogs measured here did not all exist in 2015. Newer ones skew toward AI labs and developer tools, which use more em dashes than the older cohort, so a chart of everything added together drifts upward even if not one blog changes how it writes. That is a property of the corpus, not a finding about prose.
Restricting the comparison to blogs with enough posts in both 2015–2017 and 2024–now gives a much smaller group, and among them the rate per 1,000 words is about a fifthlower than it was. Read that with its own caveat: only a handful of blogs are old enough to qualify, and half of those are newsrooms, which this data already shows barely moving. It is not evidence that nothing changed. It is a reason to trust each blog measured against its own earlier self, which is what the ranking and the per-blog pages do, and to distrust any single number claiming to describe the whole internet.
What this does not show
Nothing here identifies machine-written text. An em dash is a punctuation mark that good writers have always used, and a rising rate has plenty of innocent explanations: a new style guide, a new CMS that converts double hyphens, a change of authors, more long-form pieces. The ChatGPT marker on the charts is a date, not a cause. What the data supports is narrow and worth saying plainly: some of these blogs punctuate very differently now than they did five years ago, and some do not.
Coverage is uneven, on purpose and by accident
Not every blog is reachable to the same depth. A few refuse this crawler outright and are left out of the ranking rather than shown as blogs that happen to avoid em dashes. A few publish sitemaps listing only recent posts, so their archives are reached by paging an index or enumerating numbered sitemaps instead. The largest newsrooms publish more than can be crawled politely, so each is sampled to a fixed number of posts a month, chosen by hashing the URL so the sample is stable between runs and unbiased with respect to slug text.
Where a blog has too little prose for a rate to mean anything it is kept off the ranking, and where the crawl could not read a page that is recorded as a failure to read rather than an absence of em dashes. Each blog's own page carries its post count, its date range and how many months in that span actually carried a post.
Crawling politely
- robots.txt is fetched once per host and obeyed. A blog that disallows this crawler is skipped, not worked around.
- One request in flight per host, with a minimum gap between them, and a descriptive user agent.
- Pages are cached on disk, so a re-run fetches only what is new.
- Where a site returns a hard block, or answers with a bot challenge dressed as a normal page, that is recorded as a block and the blog is left out.