Using a New York Times API in R

Author

Ummay Rukiya

Published

November 1, 2026

Overview

For this assignment, I used the New York Times Most Popular API to investigate which newspaper sections appear most often among the most-viewed articles over the past seven days.

I will request the data in R, parse the JSON response, and organize the article records into a tidy data frame. Then I will count the articles in each section and display the results in a table and bar chart. These counts describe the articles in the returned list, rather than the total number of views each section received.

Selected API

I selected the Most Popular API’s seven-day most-viewed endpoint:

https://api.nytimes.com/svc/mostpopular/v2/viewed/7.json

The 7 specifies the seven-day period. I stored my API key privately in an environment variable named NYT_API_KEY, which allows the code to access it without including the key in this document.

Loading Required Packages

I used httr2 to make the API request, jsonlite to parse the JSON response, and dplyr to organize and summarize the articles. I used ggplot2 and knitr to present the results.

Code
library(httr2)
library(jsonlite)
library(dplyr)
library(ggplot2)
library(knitr)

Requesting the API Data

I requested the most-viewed article list for a seven-day period. The API key is read from my environment variable and added to the request. I recorded the retrieval time because the list can change.

Code
nyt_key <- Sys.getenv("NYT_API_KEY")

if (!nzchar(nyt_key)) {
  stop("Set the NYT_API_KEY environment variable before running.")
}

endpoint <- paste0(
  "https://api.nytimes.com/svc/",
  "mostpopular/v2/viewed/7.json"
)

response <- request(endpoint) |>
  req_url_query(`api-key` = nyt_key) |>
  req_perform()

retrieved_at <- Sys.time()

data.frame(
  http_status = resp_status(response),
  retrieved_at = as.character(retrieved_at)
)
  http_status               retrieved_at
1         200 2026-11-01 18:39:00.836309

Parsing the JSON Response

I parsed the response with jsonlite and extracted the article records from the results field. I then checked the number of articles and available columns.

Code
nyt_data <- fromJSON(
  resp_body_string(response),
  flatten = TRUE
)

articles_raw <- nyt_data$results

dim(articles_raw)
[1] 20 22
Code
names(articles_raw)
 [1] "uri"            "url"            "id"             "asset_id"      
 [5] "source"         "published_date" "updated"        "section"       
 [9] "subsection"     "nytdsection"    "adx_keywords"   "column"        
[13] "byline"         "type"           "title"          "abstract"      
[17] "des_facet"      "org_facet"      "per_facet"      "geo_facet"     
[21] "media"          "eta_id"        

Creating a Tidy Article Data Frame

I selected the fields needed for my question and kept one row per article. I converted publication dates to R dates, labeled missing or blank sections as “Unknown,” and kept missing author bylines as NA. Nested multimedia and keyword fields were excluded because they were not needed for the section comparison.

Code
articles_tidy <- articles_raw |>
  transmute(
    title = trimws(title),
    section = trimws(section),
    published_date = as.Date(published_date),
    byline = na_if(trimws(byline), ""),
    url = url
  ) |>
  mutate(
    section = if_else(
      is.na(section) | section == "",
      "Unknown",
      section
    )
  ) |>
  as_tibble()

dim(articles_tidy)
[1] 20  5
Code
kable(
  head(articles_tidy, 6),
  caption = "Sample of the Tidy Article Data"
)
Sample of the Tidy Article Data
title section published_date byline url
She Trusted ChatGPT With Her Medication Decisions. It Cost Her Everything. Well 2026-10-27 By Teddy Rosenbluth https://www.nytimes.com/2026/10/27/well/ai-chatgpt-medication-epilepsy-death.html
Why Are We Having Less Sex? Ask a Pornographer. Opinion 2026-10-29 By Julia Yost, Raina Raskin and Charlotte Gartenberg https://www.nytimes.com/2026/10/29/opinion/interesting-times-podcast-julia-yost-erika-lust.html
She Was Arrested After Leaving Her Kids for Days. It Sparked a Debate. U.S. 2026-10-28 By Vivian Yee https://www.nytimes.com/2026/10/28/us/florida-mother-las-vegas.html
Latest Polls Polls 2026-09-10 NA https://www.nytimes.com/interactive/polls/latest-polls.html
Ilhan Omar Investigation Involves New Scrutiny of Long-Disputed Marriage U.S. 2026-10-29 By Ernesto Londoño https://www.nytimes.com/2026/10/29/us/immigration-fraud-claims-ilhan-omar.html
Patrick Stewart, Master of Shakespeare, ‘Star Trek’ and More, Has Died Arts 2026-10-29 By Anita Gates and William McDonald https://www.nytimes.com/2026/10/29/arts/television/patrick-stewart-dead.html

Comparing Article Counts by Section

I counted the articles in each section and calculated each section’s percentage of the returned list.

Code
section_summary <- articles_tidy |>
  count(section, name = "article_count", sort = TRUE) |>
  mutate(
    percentage = round(
      article_count / sum(article_count) * 100,
      1
    )
  )

kable(
  section_summary,
  col.names = c(
    "Section",
    "Number of Articles",
    "Share of Returned Articles (%)"
  ),
  caption = "Sections in the Seven-Day Most-Viewed List"
)
Sections in the Seven-Day Most-Viewed List
Section Number of Articles Share of Returned Articles (%)
U.S. 9 45
Opinion 4 20
Arts 1 5
New York 1 5
Polls 1 5
Science 1 5
Style 1 5
Well 1 5
World 1 5

Interpretation

The U.S. section had the most articles in the returned list, with 9 out of 20 articles, or 45%. Opinion came next with 4 articles, or 20%. Together, these two sections accounted for 65% of the list.

The other seven sections each had one article. This shows that U.S. news and opinion were most represented in this seven-day snapshot. However, the API did not provide view counts, so these percentages describe the share of articles in the list rather than the share of total readership.

Visualizing the Section Counts

The bar chart compares how many articles from each section appeared in the returned list.

Code
ggplot(
  section_summary,
  aes(
    x = reorder(section, article_count),
    y = article_count
  )
) +
  geom_col(fill = "steelblue") +
  geom_text(
    aes(label = article_count),
    hjust = -0.2
  ) +
  coord_flip() +
  scale_y_continuous(
    breaks = seq(0, max(section_summary$article_count), by = 1),
    expand = expansion(mult = c(0, 0.15))
  ) +
  labs(
    title = "Sections in the NYT Seven-Day Most-Viewed List",
    x = "Section",
    y = "Number of Articles"
  ) +
  theme_minimal()

Conclusion

I successfully requested data from the New York Times Most Popular API, parsed its JSON response, and created a tidy data frame containing 20 articles and five columns. My API key was stored in an environment variable and was not included in the document.

In this snapshot, the U.S. section appeared most often, with nine articles, followed by Opinion with four. Together, they accounted for 65% of the returned articles. These results answer my question about section representation within the list, but they do not measure total views or explain why individual articles became popular.

Because the most-viewed list changes over time, running this request on another day may produce different results.