Last updated April 6, 2022

Welcome to xmlstats, an easy to use API for obtaining MLB and NBA statistics in XML and JSON. In the coming days, weeks, months more endpoints will be added. Stay tuned, much more to come...

Access Token

With the exception of the Standings and Teams endpoints, an access token is required to use the API. No new accounts are being added at this time.

Getting Started

If you are new to working with data and APIs, a great tool to familiarize yourself with is cURL. Curl is a command line program that performs HTTP requests (among many others). It is an essential developer's tool that is available as a package for most Linux distributions and is installed on all OS X systems. For Windows, you will need to download and install it on your system.

The documentation for each API endpoint shows an example request that uses curl. The quickest and simplest way to verify your access token works and that the API response is what you expect is to open a terminal window or command prompt and run curl from the command line.

Problems/Errors

Since the xmlstats API is a RESTful API, it is important to understand and work with HTTP headers. When results are not returned as expected, one of the first troubleshooting steps should be to check the HTTP headers in the response. It is likely that you will find a HTTP status code other than 200 OK as well as other headers that can be used to troubleshoot and correct the problem. When a 4xx status code is returned, it indicates a problem on the client side that you should take action to correct. Typically, these errors are returned when using an invalid or expired access token, the rate limit is exceeded, or your user agent is null or otherwise does not adhere to the user agent guidelines. A 5xx status code means the server failed to complete the request. It is possible some 5xx errors will resolve themselves in a few minutes, but ones that are persistent should be reported with information that can be used to help fix the problem such as the full request URI including all parameters and the date and time when the error occurred.

Support

For guaranteed delivery, a SLA, private/custom API endpoints, a higher rate limit, etc. please e‑mail xmlstats@erikberg.com.

Scheduled and unscheduled downtime, API updates, and status are announced on the @xmlstats Twitter account.

Rate Limit

There is no limit to how many total requests can be made to the service. However, you are not allowed to make more than six API requests per minute (i.e., one request every ten seconds). Exceeding the rate limit will return a 429 HTTP status code aka Too Many Requests. For authenticated requests, the limit is counted against your account. For unauthenticated requests, the limit is counted against the public IP address making the request.

The response of every API request contains HTTP headers about your current rate limit settings.

Header Name Description
xmlstats-api-limit Total number of requests available for time period.
xmlstats-api-remaining Number of requests available in current period.
xmlstats-api-reset Time and date represented in seconds since the Unix epoch (00:00:00 UTC, January 1, 1970) when limit is reset. The time on the xmlstats server is set using NTP for accuracy. Ensure your server does, too, if you plan to use this value.

Your program should use these HTTP headers to determine if it should make another API request in the current rate limit window or wait until the rate limit is reset. Consider this Python code snippet that illustrates making a request to the teams endpoint, then performs a loop to retrieve the roster for each team.

# retrieve teams.json, the 'http_get' function checks
# for a 200 OK response and returns the data and HTTP headers
data, xmlstats_remaining, xmlstats_reset = http_get(url)
teams = json.loads(data.decode('UTF-8'))

for team in teams:
    if xmlstats_remaining == 0:
        reset_time = datetime.fromtimestamp(xmlstats_reset)
        delta = (reset_time - datetime.now()).total_seconds()
        print('Reached rate limit. Waiting {} seconds to make new '
              'request...'.format(delta))
        time.sleep(delta)
    url = build_url(host, sport, 'roster', team['team_id'], 'json', None)
    data, xmlstats_remaining, xmlstats_reset = http_get(url)
    roster = json.loads(data.decode('UTF-8'))
    # Do something with team's roster...
    # View the Python example for the full source 

The server returns a response similar to the following when the rate limit is exceeded.

HTTP/1.1 429 Too Many Requests
xmlstats-api-limit: 6
xmlstats-api-remaining: 0
xmlstats-api-reset: 1385063580
Content-Type: application/json
Cache-Control: no-store
Pragma: no-cache
Date: Thu, 21 Nov 2013 19:52:59 GMT

{
  "error" : {
    "code" : "429",
    "description" : "API rate limit exceeded. See https://erikberg.com/api for more information."
  }
}

To avoid rate limiting, the recommended strategy is to employ caching. API responses should be cached on your server and served to your users from your cache. For example, instead of requesting an xmlstats API endpoint each time someone loads your website, request it occasionally, store it in a local cache, and serve the cached version. There are several libraries that can help accomplish this, a few notable ones include Memcached, Redis, and Ehcache.

User Agent

If you are using a robot, library, or other automated mechanism to access the API, please put a meaningful value in the user agent HTTP header. Good user agent strings include information that would help troubleshoot any problems, such as an email address or website where you can be reached and a name and version of the robot. Examples of good user agent strings:

MyRobot/1.0 (email@example.com)

MyRobot/1.0 (http://example.com/contact.html)

Each of the example code listings demonstrate how to set a user agent.

Important

Robots with user agent strings that are empty or with invalid or no contact information will receive a 403 Forbidden error message and possibly an IP ban if the behavior is not corrected.

Improper user agents will receive responses similar to the following:

HTTP/1.1 403 Forbidden
Cache-Control: no-store
Pragma: no-cache
Content-Type: application/xml;charset=UTF-8
Date: Sat, 07 Jun 2014 04:50:02 GMT

<?xml version="1.0" encoding="UTF-8"?>
<error>
  <code>403</code>
  <description>Invalid user agent: python-requests/2.5.3. Please refer to the user agent guidelines specified at https://erikberg.com/api</description>
</error>

Compression

Although XML files can be verbose, plain text compresses very well. XML and JSON file sizes are dramatically reduced when compressed. If your client advertises that it can accept gzip, responses will be delivered compressed. This is quicker for you and for me and is strongly encouraged. Chances are, the library you are using already has wide support for compression and this can be enabled easily. Please take a minute to look if you have not enabled compression already.

Character Encoding

All data is encoded in UTF-8.