Adding Application Programming Interface (API) to the BLS website

Adding Application Programming Interface (API) to the BLS website

In an effort to create transparency and encourage technological innovation, the Bureau of Labor Statistics (BLS) is releasing its Application Programming Interface (API) to the public. The BLS Public Data API gives the public access to raw economic data from all BLS programs.
read more » | leave a comment »

VN:F [1.9.22_1171]
Rating: 3.8/5 (107 votes cast)
Adding Application Programming Interface (API) to the BLS website, 3.8 out of 5 based on 107 ratings


  • Jeff September 25th, 2014 1:01 pm

    The sample seriesID from your Occupational Employment Statistics (OES) “OEUN000000011100011000001″ returns: “Series not exist”

    {“status”:”REQUEST_SUCCEEDED”,”responseTime”:126,”message”:["Series not exist for Series OEUN000000011100011000001"],”Results”:{

    curl -i -X GET

  • Gabe G August 12th, 2014 8:57 pm

    Example R code:

    ### Example signature
    ### “One or More Series, Specifying Years”
    ### per
    payload <- list(seriesid = c("LAUCN040010000000005", "LAUCN040010000000006")
    , startyear = "2010", endyear = "2012")

    ### Download data
    url <- ";
    r <- POST(url, body = toJSON(payload), add_headers("Content-Type" = "application/json"))
    r <- fromJSON(as.character(r))

    ### Turn JSON into friendly data frame
    for(i in 1:length(r$Results$series)){
    for(j in 1:length(r$Results$series[[i]]$data)){
    print(paste("seriesID", i, "period", j))
    if(i == 1 & j == 1) df <- data.frame(
    seriesID = character()
    , year = numeric()
    , period = character()
    , periodName = character()
    , value = numeric()
    , footnoteAbbr = character()
    , footnote = character()
    tDF <- df[1,]
    tDF$seriesID <- as.character(r$Results$series[[i]]$seriesID)
    tDF$year <- r$Results$series[[i]]$data[[j]]$year
    tDF$period <- as.character(r$Results$series[[i]]$data[[j]]$period)
    tDF$periodName <- r$Results$series[[i]]$data[[j]]$periodName
    tDF$value <- r$Results$series[[i]]$data[[j]]$value
    tryCatch(tDF$footnoteAbbr <-
    , error = function(err){df$footnoteAbbr[1] <- NA})
    tryCatch(tDF$footnote <-
    , error = function(err){df$footnote[1] <- NA})
    df <- rbind(df, tDF)
    rm(i, j, tDF)

  • BLS June 12th, 2014 3:24 pm

    We’re sorry, but we aren’t able to provide guidance on all the specific applications that might be used with the API. The API output we provide is in JSON (Javascript Object Notation) format, which is an open standard. We leave it up to end users to take this JSON and use it for various other formats and applications. We do provide common means of consuming the JSON using Java\Ruby\Unix at

  • Rob T June 11th, 2014 10:04 am

    Do you have an example of the multiple retrieval for VBA Excel?

  • Greg Henle May 5th, 2014 1:27 pm

    PHP Sample

    ch = curl_init();
    $this->url = is_null($url)
    ? self::DEFAULT_URL
    : $url;
    public function __destruct() {
    curl_close( $this->ch );

    public function request( $query ) {
    $this->pd = json_encode( $query );

    $this->op = array(
    CURLOPT_POSTFIELDS => $this->pd,
    sprintf(self::CONTENT_LENGTH, strlen($this->pd))
    CURLOPT_URL => $this->url

    curl_setopt_array( $this->ch, $this->op );

    $this->result = curl_exec( $this->ch );
    $this->code = curl_getinfo( $this->ch, CURLINFO_HTTP_CODE );

    $query = array(
    ‘seriesid’ => array(‘WPSFD4′, ‘WPSSOP3000′),
    ‘startyear’ => 2012,
    ‘endyear’ => 2014

    $api = new BLSAPI();
    $api->request( $query );

    var_dump( $api->code, $api->result );

  • Jim Hoffman April 14th, 2014 11:50 pm

    I recently asked if you had an example for SAS to retrieve multiple series. I have since figured it out, including adding extra filtering for the request. In addition I have figured out how to create a list of series id’s for each of the different data types.

  • Jim Hoffman April 10th, 2014 8:05 pm

    Do you have an example of the multiple retrieval for SAS. I am able to get the single retrieval but not the multiple.

  • Mark McEnearney March 10th, 2014 9:08 pm

    Very nice! Thank you. I used this python script to get data for 2 CPI series and output to ascii files.

    import requests
    import json
    import prettytable
    headers = {‘Content-type’: ‘application/json’}
    data = json.dumps({“seriesid”: ['CUUR0000SA0','SUUR0000SA0'],”startyear”:”2011″, “endyear”:”2014″})
    p =‘’, data=data, headers=headers)
    json_data = json.loads(p.text)
    for series in json_data['Results']['series']:
    x=prettytable.PrettyTable(["series id","year","period","value","footnotes"])
    seriesId = series['seriesID']
    for item in series['data']:
    year = item['year']
    period = item['period']
    value = item['value']
    for footnote in item['footnotes']:
    if footnote:
    footnotes = footnotes + footnote['text'] + ‘,’
    if ‘M01′ <= period <= 'M12': x.add_row([seriesId,year,period,value,footnotes[0:-1]])
    output = open("c:\\temp\\" + seriesId + ".txt","w")
    output.write (x.get_string())

  • BLS January 29th, 2014 10:25 am

    We’re sorry, but we aren’t able to provide guidance on all the specific applications that might be used with the API. The API output we provide is in JSON (Javascript Object Notation) format, which is an open standard. We leave it up to end users to take this JSON and use it for various other formats and applications. We do provide common means of consuming the JSON using Java\Ruby\Unix at

  • Marie M January 24th, 2014 5:38 pm

    Please provide instructions for using the API to enable PowerPivot data connections. Thx!

  • George Stevens January 18th, 2014 1:36 pm

    Thank you for responding so quickly. It appears that the API should be much more than basic data for 1-25 series. What about metadata (Eg: LNS11000000 has series title, labor force status, age). When can we get this information? When can we get more than 25 series? Can I query the database for gender = woman and get back all or top ranked series for that query term? Can you return top picks series for a given survey

    If this is really an API, how do I as a software developer create a fully functional application that is powered by the data returned by the API? Is there a way that I can query for all Age Groups that BLS has in the LN Survey? List of Areas in the CPI? List of MSA’s in the CPI related to Alabama?

    This application is either a timeseries retrieval tool or an API. I need an API.

  • BLS January 17th, 2014 4:16 pm

    Mr. Stevens, thanks for your feedback. The API features that have been added since August 2013 are listed at BLS is committed to the continued development and improvement of the API. We would be pleased to know what other features you would like to see in the API. If you still have questions, please see our Frequently Asked Questions page ( or contact us (

  • George Stevens January 17th, 2014 8:05 am

    There has been no updates since August 2013? Is this project dead or being terribly neglected by BLS management? Will this project be moved forward or die a silent death in the organization?

  • BLS January 6th, 2014 11:47 am

    Thanks for your comment. We have updated the sample code page, and the problem you were experiencing is now fixed.

  • Jan Schneider December 18th, 2013 2:41 pm

    Your Ruby sample code does not seem to be working.
    You need to submit the series id as an array and convert the parameters to JSON like so:

    require ‘rest_client’
    url = ‘’
    params = {‘seriesid’ => ['CUSR0000SA0'], ‘startyear’ => ’2005′, ‘endyear’ => ’2013′ }
    response =, params.to_json, :content_type => ‘application/json’)

    Thanks for providing this API.

  • Chuck September 16th, 2013 6:20 pm

    Excellent tool. really useful. Good job done by BLS

  • BLS August 29th, 2013 4:17 pm

    Thank you for bringing this matter to our attention. BLS developers are working to correct the problem, and the changes will be reflected in the next release of the Public Data API. We appreciate any opportunity to improve and enhance the Public Data API. We would therefore encourage you to continue to leave feedback and to inform BLS of any errors you may encounter while using the Public Data API.

  • Michel Cote August 28th, 2013 1:12 pm

    There is a problem with your API: it returns a faulty JSON string. When parsed, the value for the “Results” key is a string, not and object. The problem is evident on your “BLS Public Data Signatures” page. For example, the multiple series example shows the following partial result: “Results”: “{\n\”series\”:\n[{\”… Note the double quote before the first {. The escaped characters \n and \” also cause parsing errors.

  • Warren Glimpse August 27th, 2013 10:52 am

    Thank you for your work to develop/operate the BLS API. Among other uses, I need to access all of the QCEW data via the API. As is stands, the user is not able to access monthly or quarterly data for all NAICS levels for a county or metro (all counties, all metros). It appears that only annual data are available for these geographies. This is a request to provide this capability as soon as feasible. Thank you.

  • Michel Cote August 26th, 2013 9:00 pm

    Thank you for your response. I now realize what I was doing wrong.
    Below is an example of how to use the BLS API with AJAX and PHP to perform a cross-domain request.
    You may wish to share it with your users.

    I have posted the code at

  • BLS August 23rd, 2013 3:47 pm

    Thanks for your interest in the BLS Public Data API. Sample code for creating and consuming JSON for some of the most popular programming languages has been provided on the developer site:

    The Public Data API can only be invoked with the 3 signatures as mentioned in the developer’s site page:

    To invoke the Public Data API with a specific series and years, you would need to create a JSON request payload as described in the ‘One or More Series, Specifying Years’ section of the developer site:

  • Michel Cote August 23rd, 2013 2:29 pm

    1. Could you please provide sample code for accessing the BLS Public Data API using Javascript (preferably through AJAX)?

    2. The following URL returns 3 years of data, as expected:

    However, the following returns no data, even though the request apparently succeeded:{“seriesid”:["CES0000000001"],”startyear”:”2002″,%20″endyear”:”2012″}


    {“status”:”REQUEST_SUCCEEDED”,”responseTime”:99,”message”:[],”Results”:[{ "series": [{"seriesID":"["seriesid":["CES0000000001"],”startyear”:”2002″, “endyear”:”2012″”,”data”:[]}] }]}

Leave a Reply

View our comment policy.