Freelance journalism can be tough work. Stories that otherwise take a week or two to create, edit and upload to your blog may take twice or three times as long after you land that pitch and then go back and forth with an editor.
Sometimes the process can go smoothly and your style, wit and reporting earn the story a home at a well-respected publication. Other times, we freelancers find ourselves going a month or longer without pay with some editors, for one reason or another, haphazardly answering emails or calls – perhaps due to an obligation to hired staff.
To get a better understanding of how freelancers are paid today, Storybench teased out trends in payment by over 1,200 publications ranging from news organizations like The Washington Post to digital outlets like Atlas Obscura and Quartz. We collected the dataset in December 2018 from the crowdsourced website WhoPaysWriters.
To be sure, this is a limited sample and many of those reporting may be doing so as a form of critique. Still, we think it’s important context to have if you’re in or thinking about entering the freelancing world.
Most publications pay $0.25 per word or less
More than 60 percent of freelancers on WhoPaysWriters report being paid 25 cents per word or less. Some familiar publications in this list include Slate, NPR, Buzzfeed, Vice and The Atlantic.
So if you’re a first time writer, it might be worth taking a second to dispel the notion that the publication you idolize must pay well – according to this data, they often don’t. Of course, many writers argue that it could be worth getting a piece into a high-profile outlet like The Atlantic for less pay, if only for the name recognition. That’s a different kind of value in its own right.
Shorter pieces get higher rates
Seldom would freelancers get more than $0.50 a word for a piece longer than 2,000 words. So if you’re trying to make a living off these publications, go for quantity rather than length.
Not all publications have a hard limit on pay
It can’t be overstated that these are all just averages. Scanning meticulously through the dataset, one may notice that a publication that paid, say, $0.01 per word for an op-ed, may pay exponentially more for a feature-piece.
Take your pick of publication and you could probably find an example like this.
What some would consider the big fish of publications, the crowned jewel of writing platforms, the New York Times, has paid freelancers on a spectrum ranging from a rate of $0.10 per word all the way to $1.50 and $2.00 per word.
Some publications take two months or more to pay freelancers
Though most publications in the dataset paid freelancers within 30 days, many reported that publications like Vice, The New York Times, The Billfold and Broadly had all taken three months to pay them. The Guardian, U.S. News & World Report, The Atlantic and Rolling Stone were all said to have taken two months. A small number of freelancers wrote that they were “still waiting” for their pay at the time of reporting.
Remember, quality over quantity. Of all the story types submitted by freelancers, there is not one that averaged the highest amount of money. One-thousand-word stories for one publication could be worth the same as a 200-word piece written for another.
It seems simple, but it’s an important reminder – what one writes, the reporting and research one puts into each story, the sources one selects and the integrity one follows throughout the process is what defines a true journalist. How much that all is worth, though, remains up to the publication. As you get more experienced in the freelancing world, it’s worth noting that you may have some negotiating power. If you have the opportunity, some experienced freelancers advise finding a point at which you catalog the time you spend investing into each piece to determine a figure for the editor to consider for compensation.
library(dplyr) library(plotly) library(stringr) library(ggridges) library(forcats) payrates <- read.csv("whopayswriters.csv", header=TRUE, stringsAsFactors = FALSE) payrates$fee <- as.numeric(str_replace_all(payrates$fee, fixed("$"), "")) glimpse(payrates) ggplot(payrates, aes(fee)) + geom_histogram(stat="count") + xlab("rate") + scale_x_continuous(breaks = c(0.05, 0.5, 1, 1.50, 2, 2.5), label = c("$0.05", "$0.50", "$1.00", "$1.50", "$2.00", "$2.50")) + theme_minimal() delays <- payrates %>% select(delay) %>% na.omit() summary(delays) ggplot(delays, aes(delay)) + geom_histogram(stat="count") + scale_x_continuous(breaks = c(15, 30, 45, 60, 75, 90)) + xlab("pay delay in days") + theme_minimal() pay_and_wordcount <- payrates %>% dplyr::mutate(wordcount = str_extract(text, "\\d+")) pay_and_wordcount$wordcount <- as.numeric(pay_and_wordcount$wordcount) glimpse(pay_and_wordcount) summary(pay_and_wordcount) pay_and_wordcount_5K <- pay_and_wordcount %>% filter(wordcount < 5000) ggplot(pay_and_wordcount_5K, aes(wordcount, fee)) + geom_point() + geom_smooth() + xlab("word count") + ylab("rate") + scale_y_continuous(breaks = c(0.05, 0.5, 1, 1.50, 2, 2.5), label = c("$0.05", "$0.50", "$1.00", "$1.50", "$2.00", "$2.50")) + theme_minimal() some_pubs<-payrates %>% filter(publication == "Vice" | publication == "The New York Times" | publication == "Rolling Stone" | publication == "The Economist" | publication == "Wired" | publication == "Washington Post" | publication == "Slate" | publication == "Salon" | publication == "Broadly" | publication == "Quartz" | publication == "The Guardian" | publication == "The Atlantic" | publication == "Teen Vogue" | publication == "Pacific Standard" | publication == "Outside Online" | publication == "Npr" | publication == "New York Magazine" | publication == "Ebony" | publication == "Chicago Tribune" | publication == "Boston Globe Magazine" | publication == "Buzzfeed" | publication == "Atlas Obscura" ) ggplot(some_pubs, aes(x = fee, y = fct_rev(publication))) + geom_density_ridges(stat = "binline", bins = 20, scale = 0.95, draw_baseline = FALSE) + xlab("rate") + ylab("")+ scale_x_continuous(breaks = c(0.05, 0.5, 1, 1.50, 2, 2.5), label = c("$0.05", "$0.50", "$1.00", "$1.50", "$2.00", "$2.50")) + theme_minimal()