Weather Machine is an easy to use, universal adapter for the world’s most powerful forecast APIs.

You can use the Weather Machine with a simple JSON request, or use GraphQL for conditional fetching of specific data points.

How it works

Dark Sky’s single-response JSON format set the standard for developer friendliness: you could make just one request and get all the forecast info you need. Most other data providers require hitting multiple API endpoints and collating the responses to get similar results.

Weather Machine makes those other providers work like Dark Sky. It automatically fetches data from multiple endpoints in parallel, leveraging an advanced forecast-aware caching system to increase speed and reduce data usage along the way. The upstream responses are then collated, and each data point is run through a unit conversion layer. Finally, the data is returned as a single, well-formatted JSON response.

If you need more flexibility, all of the same systems are in place for our GraphQL API. With this approach, you’ll be able to fully customize the response format using GraphQL’s aliases, fragments, and variables. The GraphQL interface also supports conditional fetching, which means you only request the data points you need, without sacrifing the benefits of parallelization, unit conversion, and caching.

Regardless of which interface you choose, Weather Machine gives you one straightforward way to access forecasts from the world’s most powerful weather data providers, without needing to build custom implementations for each one. It’ll save you time, money, and provide a better level of service for your customers.


There are two ways to access the JSON API.

First, a drop-in compatible /forecast URL where the apiKey, latitude, and longitude are part of the path, just like Dark Sky:,-87.62

Second, an /api URL where all options are provided as query params:

Query Parameters

  • apiKey required
  • lat required
  • lon required
  • source optional
    • accuweather
    • aeris_weather
    • apple_weather
    • custom_weather
    • foreca
    • mock default
    • open_weather
    • pirate_weather
    • the_weather_company
    • tomorrow_io
    • visual_crossing
    • weatherbit
  • output optional
    • base default
    • full
  • units optional
    • us default
    • si
    • ca
    • uk
    • m

Unit options

  • us default, United States
    • precipAccumulation in
    • precipIntensity inhr
    • pressure mb
    • temperature f
    • visibility mi
    • windSpeed mph
  • si International
    • precipAccumulation cm
    • precipIntensity mmhr
    • pressure hpa
    • temperature c
    • visibility km
    • windSpeed ms
  • ca Canada
    • precipAccumulation cm
    • precipIntensity mmhr
    • pressure hpa
    • temperature c
    • visibility km
    • windSpeed kmh
  • uk United Kingdom
    • precipAccumulation cm
    • precipIntensity mmhr
    • pressure hpa
    • temperature c
    • visibility mi
    • windSpeed mph
  • m Metric
    • precipAccumulation cm
    • precipIntensity mmr
    • pressure mb
    • temperature c
    • visibility m
    • windSpeed kmh

Unit option overrides

  • precipAccumulation
    • in inches
    • cm centimeters
  • precipIntensity
    • inhr inches per hour
    • mmhr millimeters per hour
  • pressure
    • mb millibars
    • hpa hectopascals
    • kpa kilopascals
    • inhg inches of mercury
    • mmhg millimeters of mercury
  • temperature
    • f fahrenheit
    • c celsius
    • k kelvin
  • visibility
    • mi miles
    • km kilometers
    • m meters
  • windSpeed
    • mph miles per hour
    • ms meters per second
    • kmh kilometers per hour
    • kn knots
    • bft beaufort

Here’s an example request where we’re fetching data from accuweather using us units, and overriding windSpeed to be returned in knots:,-87.62?source=accuweather&units=us&windSpeed=kn

Here’s the equivalent, using the /api endpoint:


Because GraphQL requests specify the fields to be returned, our system can optimize and minimize the number of requests made to the upstream data sources. And since data sources typically charge per request, our conditional fetching system reduces data transfer, increases speed, and saves you money.

The easiest way to explore the GraphQL API is with a web-based client like GraphiQL:

From here, you can browse the schema and make requests. Here’s an example query where the arguments match the JSON examples above:

query {
    apiKey: "abc123",
    lat: 41.87,
    lon: -87.62,
    source: accuweather,
    units: us,
    windSpeed: kn
  ) {
    currently {
    daily {
      data {

When you’re ready to integrate with your app, you can select a GraphQL client and use the endpoint here:

Response Format

Both the JSON and GraphQL API return data in the same Dark Sky compatible format.

If you’re using the JSON API, you can request full output, which will include additional data points where available such as aqi and pollen. If you’re using the GraphQL API, you can request only the fields you need.

  • latitude
  • longitude
  • timezone
  • source
  • currently
    • apparentTemperature
    • aqi full
    • cloudCover
    • dewPoint
    • humidity
    • icon
    • pressure
    • pressureTrend full
    • summary
    • time
    • temperature
    • uvIndex
    • visibility
    • windBearing
    • windGust
    • windSpeed
  • minutely
    • summary
    • data
    • precipIntensity
    • precipType
    • time
  • hourly
    • summary
    • data
    • apparentTemperature
    • cloudCover
    • dewPoint
    • humidity
    • icon
    • precipAccumulation
    • precipIntensity
    • precipProbability
    • precipType
    • pressure
    • summary
    • temperature
    • time
    • uvIndex
    • visibility
    • windBearing
    • windGust full
    • windSpeed
  • daily
    • summary
    • data
    • apparentTemperatureMax
    • apparentTemperatureMin
    • aqi full
    • cloudCover
    • dewPoint
    • humidity
    • icon
    • moonPhase
    • moonPhaseName full
    • pollenGrass full
    • pollenTree full
    • pollenWeed full
    • precipAccumulation
    • precipIntensity
    • precipProbability
    • precipType
    • pressure
    • summary
    • sunriseTime
    • sunsetTime
    • temperatureMax
    • temperatureMin
    • time
    • uvIndex
    • visibility
    • windBearing
    • windSpeed
  • alerts
    • title
    • description
    • detailsUrl full
    • source full

Data Properties

  • latitude float
    • the latitude requested
  • longitude float
    • the longitude requested
  • timezone string
    • IANA timezone for the location requested, e.g. America/Chicago
  • source string
    • data source name, e.g. AccuWeather
  • currently object
    • current weather conditions
  • minutely object
    • minute-by-minute forecast, base is limited to 60 minutes, full is unbounded
  • hourly object
    • hour-by-hour forecast, base is limited to 48 hours, full is unbounded
  • daily object
    • day-by-day forecast, base is limited to 8 days, full is unbounded
  • alerts array
    • severe weather alerts
    • If there are no alerts, base omits this property and full returns an empty array

Data Blocks

(minutely, hourly, daily)

  • summary string
    • human-readable summary of the period
  • data array
    • data points for the period, in time order

Data Points

  • apparentTemperature float
    • apparent ("feels like") temperature
  • apparentTemperatureMax float
    • maximum apparent temperature
  • apparentTemperatureMin float
    • minimum apparent temperature
  • aqi integer
    • US EPA Air Quality Index, between 0 and 500, inclusive
  • apparentTemperatureMax float
    • maximum apparent temperature
  • apparentTemperatureMin float
    • minimum apparent temperature
  • cloudCover float
    • percentage of the sky covered by clouds, between 0 and 1, inclusive. (e.g. 0.75)
  • dewPoint float
    • dew point temperature
  • humidity float
    • percentage of relative humidity (e.g. 0.50)
  • icon string
    • machine-readable summary, suitable for selecting an icon for display
    • clear-day
    • clear-night
    • cloudy
    • fog
    • partly-cloudy-day
    • partly-cloudy-night
    • rain
    • sleet
    • snow
    • wind
  • moonPhase float
    • fractional part of the lunation number for the day
  • moonPhaseName string
    • machine-readable name of the moon phase
    • New
    • Waxing Crescent
    • First Quarter
    • Waxing Gibbous
    • Full
    • Waning Gibbous
    • Last Quarter
    • Waning Crescent
  • pollenGrass integer
    • level of grass pollen, between 0 and 5, inclusive
  • pollenTree integer
    • level of tree pollen, between 0 and 5, inclusive
  • pollenWeed integer
    • level of weed pollen, between 0 and 5, inclusive
  • precipAccumulation float
    • amount of snowfall accumulation
  • precipIntensity float
    • amount of liquid water, per hour
    • to calculate the total rainfall for a day, multiply the daily value by 24
  • precipProbability float
    • percentage probability of precipitation occurring (e.g. 0.35)
  • precipType string
    • type of precipitation occurring
    • rain
    • sleet
    • snow
  • pressure float
    • air pressure
  • pressureTrend string
    • air pressure trend
    • falling
    • rising
    • steady
  • summary string
    • human-readable summary
  • sunriseTime integer
    • UNIX local timestamp of when the sun will rise
  • sunsetTime integer
    • UNIX local timestamp of when the sun will set
  • temperature float
    • air temperature
  • temperatureMax float
    • maximum temperature
  • temperatureMin float
    • minimum temperature
  • time integer
    • UNIX local timestamp at the current time, or top of the period
  • uvIndex integer
    • UV index
  • visibility float
    • average visibility
  • windBearing integer
    • direction the wind is coming from in degrees
  • windGust float
    • wind gust speed
  • windSpeed float
    • wind speed


  • title string
    • brief description
  • description string
    • detailed description
  • detailsUrl string
    • link to additional details
  • source string
    • source name for use in attribution

Additional Info

By default, we allow up to 2 seconds for a data source to respond before throwing a timeout error. However, note that we monitor p99 origin latency and may increase timeouts on a per-source basis up to 5 seconds.

Some data points may not be available from all sources, and will return null when missing. If a source doesn’t provide the location’s timezone it will be fetched from GeoNames or TimeZoneDB.

We don’t yet support all of the data points and options provided by Dark Sky. However, the features we do support are fully compatible with Dark Sky, and we intend to expand support over time. If you need a data point or option that we haven’t covered yet, please get in touch!

Handling Errors

The JSON API typically returns an HTTP 200 OK response, but may return different HTTP status codes and responses if something goes wrong:

  • 200 OK
    • success
  • 400 Bad Request
    • invalid parameters, e.g. invalid source, disabled source, or invalid options
  • 401 Unauthorized
    • invalid Weather Machine API Key
  • 407 Proxy Authentication Required
    • invalid source credentials
  • 429 Too Many Requests
    • source rate limit error
  • 500 Internal Server Error
    • something went wrong with the Weather Machine
  • 502 Bad Gateway
    • source data error
  • 504 Gateway Timeout
    • source timeout

Note that the GraphQL API will always return a 200 OK response unless there’s a 500 Internal Server Error. For a successful response, the data object will contain the requested fields. In the case of an error or timeout, the data object will be null and the errors object will contain description matching the JSON API.

  "data": null,
  "errors": [{ "message": "Gateway Timeout: source timeout" }]


To begin using the Weather Machine, sign up for an account and visit the Dashboard to view your API key:

You’ll use your API key to authenticate requests so they’re associated with your account. Your API key can be provided in a few different ways:

  • GraphQL API
    • query { weather(apiKey: "abc123") }
  • HTTP Header
    • Authorization: Bearer abc123

The HTTP Header method works for both the JSON and GraphQL APIs.

Adding Sources

When you’re getting started, you can experiment with the "Mock" source, which returns static data. When you’re ready to use real data sources, you’ll need to enable them on your account:

If you’re already using a weather data provider for your application, simply add your data provider’s credentials to your Weather Machine account.

If you don’t have a data provider yet, you’ll need to sign up for one first and then add it to your Weather Machine account.

Rest assured that your credentials are encrypted, never accessed without your prior authorization, and never shared between accounts.

Monitoring Usage

You can monitor your usage and cache hit ratio across all sources, or drill down to individual sources by month and day. Usage data is updated every 15 minutes.

Weather Machine caches the responses received from data sources into static time buckets. For example, we cache hourly data until the end of the current hour. The logic works as follows:

  • currently and alerts (max: 15 minutes)
    • beginning of current hour + a sliding 15 minute "bucket"
    • (:00, :15, :30, :45)
  • minutely (max: 1 minute)
    • beginning of current minute + 1 minute
  • hourly (max: 1 hour)
    • beginning of current hour + 1 hour
  • daily (max: 3 hours)
    • beginning of the current day + a sliding 3 hour "bucket"
    • (00:, 03:, 06:, 09:, 12:, 15:, 18:, 21:)
  • weekly (max: 1 week)
    • current time + 1 week

By default, latitude and longitude are rounded to 3 decimal places to optimally balance cacheability and accuracy. This allows for precision of approximately 111 meters, 365 feet, or about the size of a city block.

Weather Machine’s caching system is designed to be fast, effective, and fair to both our customers and data sources. All data caches are segmented by customer, and customers can only access data from their own cache.

Data Attribution

You’re not required to provide attribution to Weather Machine, but it’s always appreciated. Simply link to and feel free to use the logo at the top of this page.

Most weather data sources have strict attribution requirements, so make sure to review their terms of service. We do our best to provide relevant links on the source pages where possible, but of course you’ll need to abide by any terms you’ve agreed to with them.

Contact Us

We’re excited to share Weather Machine with you, and we’re just getting started. Please let us know if you have any questions or comments. Missing a data point? Missing a data source? Want to work with us? Please don’t hesitate to get in touch.