An API Wrapper for the Bureau of Labor Statistics (BLS)

Scrapes various data from the Bureau of Labor Statistics, which is the statistical branch of the United States Department of Labor. The package has additional functions to help parse, analyze and visualize the data.

Designed to be a better API wrapper for the Bureau of Labor Statistics (BLS.) The package has additional functions to help parse, analyze and visualize the data. Fundamental ideas borrowed from the acs package, which has similar functionality for the Census Bureau API.

  • Stable version from CRAN:
  • The latest development version from GitHub:

Before getting started, you’ll probably want to head over to the BLS and get set up with an API key. While an API key is not required to use the package, the query limits are much higher if you have a key and you’ll have access to more data. Plus, it’s free (as in beer), so why not?

For “quick and dirty” type of analysis, the package has some quick functions that will pull metrics from the API without series numbers. These quick functions include unemployment, employment, and civilian labor force on a national level.

df <- quick_unemp_rate()
tail(df, 5)
#> 2 {                                           
#> 3     if (missing(ncp))                       
#> 4         .Call(C_df, x, df1, df2, log)       
#> 5     else .Call(C_dnf, x, df1, df2, ncp, log)
#> 6 }

DISCLAIMER: Some working knowledge of BLS series numbers are required here. The BLS claims that they “do not currently have a catalog of series IDs.” The BLS Data Finder website is a good place to nail down the series numbers we're looking for.

You should consider getting an API key form the BLS. The package has a function to install your key in your .Renviron so you’ll only have to worry about it once. Plus, it will add extra security by not having your key hard-coded in your scripts for all the world to see.

Service Version 2.0 (Registered) Version 1.0 (Unregistered)
Daily query limit 500 25
Series per query limit 50 25
Years per query limit 20 10
Net/Percent Changes Yes No
Optional annual averages Yes No
Series descriptions Yes No
# First time, reload your enviornment so you can use the key without restarting R.
# You can check it with:

Note: The above script will add a line to your .Renviron file to be re-used when ever you are in the package. If you are not comfortable with that, you can add the following line to your .Renviron file manually to produce the same result.


Now that you have an API key installed, you can call your key in the package’s function arguments with "BLS_KEY". Don't forget the quotes! If you just HAVE to have your key hard-coded in your scripts, you can also pass they key as a string.

# Median Usual Weekly Earnings by Occupation, Unadjusted Second Quartile.
# In current dollars
df <- bls_api(c("LEU0254530800", "LEU0254530600"),
                startyear = 2000, endyear = 2015,
                registrationKey = "BLS_KEY")
# A little help from ggplot2!
ggplot(df, aes(x=date, y=value, color=seriesID)) +
    geom_line() +
    labs(title = "Median Weekly Earnings by Occupation") +
    theme(legend.position="top") +
        breaks=c("LEU0254530800", "LEU0254530600"),
        labels=c("Database Admins.", "Software Devs."))

For more advanced usage, please see the package vignettes.

Like the the “quick functions” for requesting API data, there are two "quick" map functions, bls_map_county() and bls_map_state(). These functions are designed to work with two helper functions get_bls_county() and get get_bls_state(). Each helper function downloads recent data for unemployment rate, unemployment level, employment rate, employment level and civilian labor force. These functions do not pull data from the API, rather they pull data from text files and do not count against daily query limits.

Note: Even though the get_bls functions return data in the correct formats, the bls_map functions can be used with any data set that includes FIPS codes.

The example below maps the current unemployment rate by county. Alaska and Hawaii have to re-located to save space.

# Grap the data in a pre-formatted data frame.
# If no argument is passed to the function it will load the most recent month's data.
df <- get_bls_county()
#Use map function with arguments.
bls_map_county(map_data = df, fill_rate = "unemployed_rate", 
               labtitle = "Unemployment Rate by County")

What's R mapping without some interactivity? Below we’re using two additional packages, leaflet, which is popular for creating interactive maps and tigris, which allows us to download the exact shape files we need for these data and includes a few other nice tools.

# Leaflet map
map.shape <- counties(cb = TRUE, year = 2015)
df <- get_bls_county()
# Slice the df down to only the variables we need and rename "fips" colunm
# so I can get a cleaner merge later.
df <- df[, c("unemployed_rate", "fips")]
colnames(df) <- c("unemployed_rate", "GEOID")
# Merge df with spatial object.
leafmap <- geo_join(map.shape, df, by="GEOID")
# Format popup data for leaflet map.
popup_dat <- paste0("<strong>County: </strong>", 
                    "<br><strong>Value: </strong>", 
pal <- colorQuantile("YlOrRd", NULL, n = 20)
# Render final map in leaflet.
leaflet(data = leafmap) %>% addTiles() %>%
    addPolygons(fillColor = ~pal(unemployed_rate), 
                fillOpacity = 0.8, 
                color = "#BDBDC3", 
                weight = 1,
                popup = popup_dat)

Note: This is just a static image since the full map would not be as portable for the purpose of documentation.


blscrapeR 2.0.0

  • The BLS changed their servers from http to https. API protocols changed in accordance.


  • FIPS fix for the get_bls_state() function.

blscrapeR 1.0.2

  • Updated URLs for the get_bls_state() function.
  • Updated tests for the get_bls_state() function.

blscrapeR 1.0.1

  • The BLS changed the location of their county level employment data on the server side. Changes were made in the get_bls_county() function that were not backwards compatible.
  • Added the qcew_api() function to gather data from the BLS Quarterly Census of Employment and Wages. This API is owned by the QCEW and is seperate from the main BLS API.

  • Added 404 error handling to the main bls_api() function.

  • Added three data sets; niacs, size_titles, and area_titles. These data sets act as helpers for the QCEW API and provide industry and area codes that the API regularly uses.
  • Updated URLs for the get_bls_county() function.
  • Added documentation for the qcew_api() function.

  • Added documentation for the three new data sets; niacs, size_titles, and area_titles.

  • Added a vignette for the qcew_api() function.

  • Added a test for the qcew_api() function.

blscrapeR 0.4.2

  • Added stateName argument to get_bls_county() that allows user to specify a state or list of states.

  • Added stateName argument to map_bls_county() that allows user to specify state(s) to map.

  • Added mapping vignette.

  • Added manual pages for the county_map_data and state_map_data internal data sets.

  • Added tigris and broom packages to prep_maps.R in data-raw folder.
  • Fixed date argument in get_bls_county() and get_bls_state() to return the most recent date if argument is NULL.

  • Added error handling to map_bls_state() and map_bls_county().

  • Added tests for map_bls_state() and map_bls_county() to the /testthat directory.

blscrapeR 0.4.1

  • Added quick functions to pull popular data sets from the API without the need of the user inputing a series id.

  • Addded data argument to get_bls_county. If NULL the function will return the most recent month.

  • Added the inflaction_adjust() function to help users with calculating inflation from the CPI. Since the API will only allow twenty years of data, the inflation function pulls data from a text file instead that allows the user to get CPI data back to 1947.

  • Added more error handling to bls_api() function.

  • Added documentation to get_bls_county() to explain the new date argument.

  • Added package vignettes.

blscrapeR 0.4.0

  • Added the set_bls_key() function to be used with the bls_api() function. The new function writes the user's api key to the Renviron. The change is backward compatible since the user is sill able to enter their api key as a string. However, for security purposes, the stored key method is preferred and should be promoted.

  • Added testthat directory and added test_bls_api.R. The tests won't affect anything in the package functionality, but will be useful for future testing.

  • Truncated the bls_state_data() function and added those features to the get_bls_state() function.

  • Removed dplyr from imports since it's not necessary anymore. Added leaflet and cron to package recommends.

  • Renamed blscrape.R to bls_api.R since the bls_api() function was the only function in that file.

  • Added testthat to recommends.

blscrapeR 0.3.2

  • Revised the map prep in data-raw to render smaller data frames, thereby making the total package size much smaller.

  • Added a label title argument to map functions bls_map_state() and bls_map_county()

  • Standardized colnames in all returned data frames throughout the package.

  • Truncated the inflation() function for now. The API seems to return adjusted dollar-values.
  • Made documentation for helper functions invisable in the manual.

  • Added News.Rd

blscrapeR 0.3.1

  • Changed name of county_map() to avoid conflicts with other packages. I didn't mark this as a major release becasue no other functions in the package are dependant on this.

  • Various fixes in map functions including removing unused themes and general code tidyness.

  • Various fixes to examples.

  • Made descriptions more robust.

blscrapeR 0.3.0

  • Changed name of get_data() to bls_api() to avoid any problems in the global environment. Bumped the version to 0.3.0 because this is the primary workhorse function of the package.

blscrapeR 0.2.1

  • Added custom maps rendered from shape files
  • Removed shape files from package data to cut down on size. This fundamentaly changes the way the mapping functions work. Opted instead, for spacial poly data frames rendered from the shapefiles.

blscrapeR 0.2.0

  • Complete re-write of old get_data() function to pull from API only.

  • Added arguments to get_data() to pass the BLS API perams.

blscrapeR 0.1.0

  • Added bls_state_data() function to pull most recent sate-level employment data for mapping.

  • Added arguments to get_data() to pass the BLS API perams.

  • Added documentation for data sets.

  • Fixed zoo::index() error.

Reference manual

It appears you don't have a PDF plugin for this browser. You can click here to download the reference manual.


2.1.2 by Kris Eberwein, 23 days ago

Report a bug at

Browse source code at

Authors: Kris Eberwein [aut, cre]

Documentation:   PDF Manual  

MIT + file LICENSE license

Imports httr, jsonlite, ggplot2, magrittr, utils, stats, grDevices

Suggests testthat, knitr, rmarkdown, dplyr

See at CRAN