Library / SDK
meteostat/meteostat avatar
meteostat/meteostat

meteostat turns nearby weather stations into one series for your location

Access and analyze historical weather and climate data with Python.

664 stars82 forksPythonMIT

At a glance

What is it?
Meteostat is an MIT licensed Python package for historical weather and climate data that finds the stations near a point, pulls their daily or hourly observations and interpolates them into a single series for the coordinates you asked about, and its data, unlike its code, is licensed separately.
Who is it for?
meteostat fits a data scientist who needs one clean series for a specific location rather than a catalogue of station files, since the nearby lookup and the interpolation step are the part that takes real work to do by hand. It does not fit a project that needs the raw observations per station, because the API is built around the interpolated point series, and it does not fit an environment that cannot reach the network, since the package depends on requests.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 28 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What the package is for

Meteostat is a Python package for accessing and analysing historical weather and climate data, published on PyPI as meteostat, with documentation at dev.meteostat.net/python and a wider project site at meteostat.net.

The subject is the raw observation record of weather stations, but the API is organised around a place rather than around a station. You give it a point, it finds the stations around that point, pulls their observations for a time range, and interpolates them into a single series for the location you asked about.

That is the design decision that makes the package useful and also the one that limits it. A user who wants the readings of one specific station with its own quirks gets a harder time than a user who wants a smooth series for a city, and a user who wants to audit the raw numbers has to go around the abstraction rather than through it.

The example scripts shipped in the repository show how wide the surface is: chart.py, daily.py, hourly.py, monthly.py, normals.py, inventory.py, meta.py, nearby.py, interpolation.py, provider.py and gsa.py. So there is a daily series, an hourly series, monthly aggregates, climate normals, an inventory of what is available for a station, metadata, a nearby lookup, the interpolation step, and a provider module that suggests the data source is behind an interface.

Installing and plotting a year of temperature

Installation is a single pip command:

sh
pip install meteostat

The usage example plots 2018 temperature data for Frankfurt, Germany, and it is short enough to read as an API tour:

python
from datetime import date
import matplotlib.pyplot as plt
import meteostat as ms

# Specify location and time range
POINT = ms.Point(50.1155, 8.6842, 113)  # Try with your location
START = date(2018, 1, 1)
END = date(2018, 12, 31)

# Get nearby weather stations
stations = ms.stations.nearby(POINT, limit=4)

# Get daily data & perform interpolation
ts = ms.daily(stations, START, END)
df = ms.interpolate(ts, POINT).fetch()

# Plot line chart including average, minimum and maximum temperature
df.plot(y=[ms.Parameter.TEMP, ms.Parameter.TMIN, ms.Parameter.TMAX])
plt.show()

Six calls do the work. ms.Point takes latitude, longitude and an elevation, which is the third argument in the example, 113 metres for that location. stations.nearby takes that point and a limit, here four stations. ms.daily pulls the daily series for those stations over the date range, ms.interpolate turns the station series into an interpolated one for the point, and fetch materialises it as a pandas DataFrame. The parameters themselves are named constants, ms.Parameter.TEMP with TMIN and TMAX, so the column names are not string literals scattered through your code.

The final call is ordinary pandas, which is the point: the result is a DataFrame, so everything you already do with a DataFrame applies.

Why the interpolation step exists at all

Weather stations are not where you are. A city rarely has a station in it, and the nearest station may sit on an airfield, on a rooftop or in a different climate, which is why the package takes a point with an elevation and hands the observations to an interpolation step instead of returning the raw station readings.

The flow is the interesting part. ms.daily returns a time series for a set of stations, and ms.interpolate takes that series and a point and returns something that can be fetched into a DataFrame. The nearby lookup with a limit is the input to that, so the number of stations you allow directly affects how the interpolation is weighted, and four is the value the example uses.

The elevation in the Point is there for the same reason. Temperature and pressure vary with height, so a point that only carried coordinates would produce a series for a location at sea level.

The provider module and the provider-tests CI workflow badge point at a further layer: the data source is behind an interface that the project tests separately, which is the arrangement you would want if you were going to point the package at a different source of observations.

Dependencies that tell you what it returns and what it needs

The project metadata is built with Poetry, and the runtime dependencies are short:

toml
[tool.poetry.dependencies]
python = "^3.11"
requests = "^2.31.0"
pandas = ">=2.3.0,<4.0.0"
pytz = "^2023.3.post1"

Three of those say something concrete. pandas is the output format, and the floor is high, 2.3.0, with an upper bound below 4.0.0, so a project on an older pandas cannot use the current release. pytz handles time zones, which matters for a dataset assembled from observations recorded in local time at stations around the world. requests is the HTTP client, and its presence says plainly that the data is fetched over the network rather than shipped inside the package, so the library needs connectivity and a server to talk to.

The optional extras are matplotlib for plotting, metar, which is the format meteorological observations are transmitted in, and lxml for XML parsing, which is how the aviation weather formats are read. The example scripts use matplotlib, and the METAR dependency points at aviation weather as one of the sources.

The development group is pytest with pytest-mock and pytest-cov, ruff for linting and a type checker called ty, which is a young tool, at version 0.0.1a33, so this project is experimenting with its type checking setup. The pytest configuration names the test paths and the file and function naming patterns, and the coverage configuration excludes protocol classes and abstract methods, which tells you the code is shaped around an interface hierarchy.

The licence split is the detail to read twice

There are two licences in play and they cover different things.

The code is licensed under the MIT Licence, with the LICENSE file at the repository root, and the README states it directly. The data provided by Meteostat is licensed under the Creative Commons Attribution 4.0 International licence, and the README points to the licence documentation for more information.

That distinction is more than boilerplate for a data project. The code licence is about how you may use the library, which is permissive and unencumbered. The data licence requires attribution, which means a chart, a model or a report that shows Meteostat data has to say where it came from. A commercial dashboard built on the interpolated series inherits that obligation, and the fact that the data arrives through an HTTP call rather than as a file in your repository does not change it.

The repository also carries a CITATION.cff file, so a paper that used this data can be cited properly, and a documentation page dedicated to the licence rather than a paragraph in the readme, which is where the details belong.

Release cadence, Python floor, and the alternative

The release history is steady. The most recent versions are v2.1.5 published on 2026-09-17, v2.1.4 on 2026-03-21 and v2.1.3 on 2026-02-14. The repository is not archived and the last push was on 2026-09-25, so the work is current, and the current version in the metadata is 2.1.5, matching the newest release.

The two floors to keep in mind are Python 3.11 and pandas 2.3.0, both of which arrived with the 2.x line. That is a reasonable stance for a library that maintains a modern data stack, and it also means an older project cannot simply bump a version number.

The alternative is to use a general purpose weather API or to download station files yourself. The difference in approach is what the data is: a general API typically returns model or gridded values for a coordinate, whereas Meteostat's model is built on observed station data with an interpolation step that produces a point series from the surrounding stations. For a climate application where the observation record is what matters, that is the better source, and the cost is that you depend on the Meteostat API and on its choice of stations, and you inherit its interpolation rather than choosing your own method.

For a researcher who needs the station records themselves, the raw files behind a service like this are the better starting point, and the value of the package is that it has already done the hard part of assembling a coherent point series from them.

Editorial conclusion

meteostat fits a data scientist who needs one clean series for a specific location rather than a catalogue of station files, since the nearby lookup and the interpolation step are the part that takes real work to do by hand. It does not fit a project that needs the raw observations per station, because the API is built around the interpolated point series, and it does not fit an environment that cannot reach the network, since the package depends on requests. Before using it, check the licence split, since the code is MIT but the data is CC BY 4.0, and pin the version, because the 2.x line has moved the pandas floor to 2.3.0 and the Python floor to 3.11.

Frequently asked questions

How do I install meteostat and get a time series for a location?

Install it with pip install meteostat, build a ms.Point from latitude, longitude and elevation, find nearby stations with ms.stations.nearby(POINT, limit=4), pull the daily series with ms.daily(stations, START, END), and interpolate it for the point with ms.interpolate(ts, POINT).fetch().

What data format does meteostat return?

A pandas DataFrame. The runtime dependencies include pandas at 2.3.0 or later and below 4.0.0, and the README example plots the result directly with df.plot using the ms.Parameter constants for temperature, minimum and maximum.

Which licence applies to the meteostat code and the data?

The code is licensed under the MIT Licence, and the data provided by Meteostat is generally licensed under the Creative Commons Attribution 4.0 International licence, with the details on the project's licence documentation page.

What Python and pandas versions does meteostat require?

The project metadata requires Python ^3.11 and pandas >=2.3.0,<4.0.0, along with requests and pytz. The optional extras add matplotlib, metar and lxml.

How recent is the latest meteostat release?

The most recent release is v2.1.5 on 2026-09-17, before it v2.1.4 on 2026-03-21 and v2.1.3 on 2026-02-14, and the last push to the repository was on 2026-09-25.

Official sources

  1. License: MIT
  2. meteostat/meteostat on GitHub
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/meteostat-meteostat.svg)](https://hysenlabs.com/projects/meteostat-meteostat)

Was this useful?