Today, March 31st 2023, the excellent Dark Sky API, a quite popular weather forecast service, is going... well... dark. It is now part of Apple Weather and replaced by WeatherKit.
If you used Dark Sky for iOS 16 apps, you will have probably already migrated to WeatherKit. For any other platform, including older iOS versions, you'd need something else, with various possible options starting with Apple's own WeatherKit REST API.
Read on if you are either having issues accessing the WeatherKit REST API, or you want a completely free alternative and I'll share some tips and solutions from my experience porting my own app Xasteria Plus.
WeatherKit REST API
Apple thankfully provides a REST API that is mostly a complete replacement of Dark Sky - however there are a couple of "gotchas". Firstly, we should note that part of the appeal of Dark Sky was its cost: free for up to 1000 calls/day. The WeatherKit API requires an Apple developer account, which costs $99/year. With that cost though, it allows 500k requests per month, so if you already have a developer account it's a great deal. Secondly, instead of a simple API key you can pass with your request, the service requires passing signed developer tokens (JWT) with the request header, which requires some setup.
If the first issue (the developer account) is no problem, I can assist with the second, otherwise jump to the next section. Here are the steps you will need to follow:
Setup
- Register a new WeatherKit key in the Certificates, IDs & Profiles section of the Apple developer portal. Download the key in the last step and you'll have a file named like
AuthKey_YOURKEYID.p8
. - The key is in the PKCS8 format, in most cases you'll need to convert to the PEM format. On a Mac you can convert it simply:
openssl pkcs8 -nocrypt -in AuthKey_YOURKEYID.p8 -out AuthKey_YOURKEYID.pem
- Back on Certificates, IDs & Profiles you'll need to provision a new Service ID. You'll normally use the reverse-domain notation for it (com.mycompany.myapp).
- Locate your Team ID - it's under Membership Details on the Apple developer portal.
Accessing the API
You now have what you need (Team ID, PEM key, Key ID, service ID) to create a JSON Web Token to access the API per the official documentation. The token is used in the header of the api request, e.g.:
curl -v -H 'Authorization: Bearer [developer token]' "https://weatherkit.apple.com/api/v1/availability/37.323/122.032?country=US"
Easy access with Perl / Weather::WeatherKit
For my own app, I created the Perl module Weather::WeatherKit, which takes care of all the token creation etc. It makes it very simple if you use Perl, but even if you don't you can still make a full WeatherKit API proxy in a few lines of code as I'll demonstrate - which you can then access any way you like.
Why Perl? Despite the flak it gets from devs who don't use it, it's still a great solution for many tasks and I still prefer it over python for those tasks. Also, it's already available or readily available on most systems (Mac/Linux/BSD), but if you'd like to have one of the latest versions, a good way to get it is via perlbrew:
\curl -L https://install.perlbrew.pl | bash
perlbrew install perl-5.36.0
perlbrew switch perl-5.36.0
Apart from Perl, you'll need a package manager to make your life easier, like cpanm. On linux you'd use apt/yum to install a package called something like cpanminus
or perl-App-cpanminus
, while if you used perlbrew you'd do:
perlbrew install-cpanm
You can now install the two packages we'll use. I will use Mojolicious, which is a modern web app framework, so that I am not accused of using your grandpa's CGI:
cpanm Mojolicious::Lite Weather::WeatherKit
The full code for a proxy that handles the authentication follows:
#!/usr/bin/env perl
use Mojolicious::Lite -signatures;
use Weather::WeatherKit;
any '/weather' => sub ($c) {
my %params = map {$_ => $c->param($_)} $c->req->params->names->@*;
my $weather = Weather::WeatherKit->new(
team_id => "TEAMID",
service_id => "com.mycompany.myapp",
key_id => "YOURKEYID",
key_file => "AuthKey_YOURKEYID.pem"
);
my $res = $weather->get(%params);
$c->render(text => $res);
};
app->start;
Assuming you saved the above as weather-server.pl
and put it in the same directory as your .pem
key, you can start it as a web service that listens to port 3000 with:
morbo cgi-bin/weather-server.pl
After that, simply point a browser to http://127.0.0.1:3000/weather?lat=51.2&lon=-1.8&dataSets=forecastHourly
and you'll get a hourly forecast for the next day for Stonehenge in JSON format:
{
"forecastHourly":{
"name":"HourlyForecast",
"metadata":{
"attributionURL":"https://weatherkit.apple.com/legal-attribution.html",
"expireTime":"2023-03-31T10:41:14Z",
"latitude":51.2,
"longitude":-1.8,
"readTime":"2023-03-31T09:41:14Z",
"reportedTime":"2023-03-31T08:05:04Z",
"units":"m",
"version":1
},
"hours":[
{
"forecastStart":"2023-03-31T09:00:00Z",
"cloudCover":0.98,
"conditionCode":"Drizzle",
"daylight":true,
"humidity":0.89,
"precipitationAmount":0.5,
"precipitationIntensity":0.5,
"precipitationChance":0.7,
"precipitationType":"rain",
"pressure":984.31,
"pressureTrend":"rising",
"snowfallIntensity":0,
"snowfallAmount":0,
"temperature":9.9,
"temperatureApparent":6.07,
"temperatureDewPoint":8.18,
"uvIndex":1,
"visibility":7558.44,
"windDirection":242,
"windGust":57.61,
"windSpeed":35.96
},
...
7Timer and other free solutions
7Timer
7Timer is a completely free service based on NOAA's GFS. It's notable for calculating astronomical seeing and atmospheric transparency, which are very useful to astronomers and stargazers. I am donating the servers to the project and developing the iOS client Xasteria (also free).
You can check the documentation for the available forecast products and the meaning of the output values. If you use Perl, you can use Weather::Astro7Timer to access the service in your code, otherwise here are a couple of example requests, one for the 3-day ASTRO forecast, and one for the 7-day CIVIL forecast:
http://www.7timer.info/bin/astro.php?lat=51.2&lon=-1.8&output=json
http://www.7timer.info/bin/civil.php?lat=51.2&lon=-1.8&output=json
Try them on your browser.
MET Norway
The Norwegian Meteorological Institute offers a number of APIs. Their forecast API Locationforecast 2.0 is based on the European ECMWF forecast and it's a great solution, especially for users not interested in the astronomical aspects of 7Timer. It's completely free/open like 7Timer, so all you have to do to get a forecast is a request like this:
https://api.met.no/weatherapi/locationforecast/2.0/complete?lat=51.2&lon=-1.8
Personally, given that MET Norway, 7Timer and Apple Weather are based on different forecast models, I find that consulting these three gives me a better forecast confidence (a hard thing here in the UK).
OpenWeather
OpenWeather is a bit more like Dark Sky in that you have to sign up to get a key and then you get 1000 free requests per day (One Call API). So it may be completely free if it fits your usage needs.
Their various API options may seem a bit confusing, but basically if you want something similar to Dark Sky, you would go with the aforementioned One Call API that provides current weather and minutely, hourly, daily forecasts in the future, or their 5 day / 3h forecast. The latter has a greater free quota of 60 calls/min or 1 million per month.
Top comments (1)
Thanks for the write-up on WeatherKit. There's also an open source CLI weather app that I'm aware of, wttr.in. It's written in GO, and is fairly useful.