Baseline Surface Radiation Network (BSRN)#

The Baseline Surface Radiation Network (BSRN) is a global network of high-quality solar radiation monitoring stations under the World Climate Research Programme (WCRP) [].

According to the World Radiation Monitoring Center (WRMC):

The data [from the BSRN stations] are of primary importance in supporting the validation and confirmation of satellite and computer model estimates of these quantities. At a small number of stations (currently 74 in total, 58 active) in contrasting climatic zones, covering a latitude range from 80°N to 90°S, solar and atmospheric radiation is measured with instruments of the highest available accuracy and with high time resolution.

All BSRN stations are required to meet the basic station requirements. A list of activate, inactive, and candidate BSRN stations can be retrieved from the SolarStations station listing and are shown below.

import pandas as pd

stations = pd.read_csv('solarstations.csv', sep=';', encoding='latin1')
stations = stations[stations['Network'].str.contains('BSRN')]
stations['Time period'] = stations['Time period'].astype(str).replace('nan','')
FileNotFoundError                         Traceback (most recent call last)
/tmp/ipykernel_1835/ in <module>
      1 import pandas as pd
----> 3 stations = pd.read_csv('solarstations.csv', sep=';', encoding='latin1')
      4 stations = stations[stations['Network'].str.contains('BSRN')]
      5 stations['Time period'] = stations['Time period'].astype(str).replace('nan','')

/opt/hostedtoolcache/Python/3.7.13/x64/lib/python3.7/site-packages/pandas/util/ in wrapper(*args, **kwargs)
    309                     stacklevel=stacklevel,
    310                 )
--> 311             return func(*args, **kwargs)
    313         return wrapper

/opt/hostedtoolcache/Python/3.7.13/x64/lib/python3.7/site-packages/pandas/io/parsers/ in read_csv(filepath_or_buffer, sep, delimiter, header, names, index_col, usecols, squeeze, prefix, mangle_dupe_cols, dtype, engine, converters, true_values, false_values, skipinitialspace, skiprows, skipfooter, nrows, na_values, keep_default_na, na_filter, verbose, skip_blank_lines, parse_dates, infer_datetime_format, keep_date_col, date_parser, dayfirst, cache_dates, iterator, chunksize, compression, thousands, decimal, lineterminator, quotechar, quoting, doublequote, escapechar, comment, encoding, encoding_errors, dialect, error_bad_lines, warn_bad_lines, on_bad_lines, delim_whitespace, low_memory, memory_map, float_precision, storage_options)
    584     kwds.update(kwds_defaults)
--> 586     return _read(filepath_or_buffer, kwds)

/opt/hostedtoolcache/Python/3.7.13/x64/lib/python3.7/site-packages/pandas/io/parsers/ in _read(filepath_or_buffer, kwds)
    481     # Create the parser.
--> 482     parser = TextFileReader(filepath_or_buffer, **kwds)
    484     if chunksize or iterator:

/opt/hostedtoolcache/Python/3.7.13/x64/lib/python3.7/site-packages/pandas/io/parsers/ in __init__(self, f, engine, **kwds)
    809             self.options["has_index_names"] = kwds["has_index_names"]
--> 811         self._engine = self._make_engine(self.engine)
    813     def close(self):

/opt/hostedtoolcache/Python/3.7.13/x64/lib/python3.7/site-packages/pandas/io/parsers/ in _make_engine(self, engine)
   1038             )
   1039         # error: Too many arguments for "ParserBase"
-> 1040         return mapping[engine](self.f, **self.options)  # type: ignore[call-arg]
   1042     def _failover_to_python(self):

/opt/hostedtoolcache/Python/3.7.13/x64/lib/python3.7/site-packages/pandas/io/parsers/ in __init__(self, src, **kwds)
     50         # open handles
---> 51         self._open_handles(src, kwds)
     52         assert self.handles is not None

/opt/hostedtoolcache/Python/3.7.13/x64/lib/python3.7/site-packages/pandas/io/parsers/ in _open_handles(self, src, kwds)
    227             memory_map=kwds.get("memory_map", False),
    228             storage_options=kwds.get("storage_options", None),
--> 229             errors=kwds.get("encoding_errors", "strict"),
    230         )

/opt/hostedtoolcache/Python/3.7.13/x64/lib/python3.7/site-packages/pandas/io/ in get_handle(path_or_buf, mode, encoding, compression, memory_map, is_text, errors, storage_options)
    705                 encoding=ioargs.encoding,
    706                 errors=errors,
--> 707                 newline="",
    708             )
    709         else:

FileNotFoundError: [Errno 2] No such file or directory: 'solarstations.csv'
Make this Notebook Trusted to load map: File -> Trust Notebook

Station requirements#

As a mimimum a BSRN station is required to measure global horizontal irradiance (GHI), direct normal irradiance (DNI), diffuse horizontal irradiance (DHI),

Additional metadata may be found at the BSRN website and in the individual data files (e.g., horizon profile).


Unlike the majority of solar radiation monitoring networks, the BSRN website does not have a subpage for each station (with photos, etc.). This would have been very useful when assessing the usage of the station, for example in regards to the potential impact of nearby structures, etc. Note a few photos of the BSRN stations can be found here. There station log books are also not available. It should also be noted that the files on the FTP server do not include wind speed and direction.

Data retrieval#

Data from the BSRN stations is stored in monthly files for each station and can be freely downloaded either via FTP or Pangea. Credentials for accessing the BSRN FTP server can be obtained as described in the data release guidelines.

Data release guidelines

Please read the BSRN data release guidelines before using any data and make sure to properly cite the BSRN.


WRMC highly recommends that all users do their own quality checks of the data after extracting BSRN-data!

The data can also be downloaded programmatically using the pvlib-python library, specifically the get_bsrn function. An example of how to use pvlib to download two months of data from the Cabauw (CAB) station is shown below:

import pvlib

df, meta = pvlib.iotools.get_bsrn(
    station='CAB',  # three letter code for the Cabauw station
    username=bsrn_username,  # replace with your own username
    password=bsrn_password,  # replace with your own password


For a description of the input parameters, see the pvlib documentation.

Retrieving BSRN data in R

R users can find similar functionality in the SolarData R package.

The data retrieved from all BSRN stations includes measurements of the three irradiance components, as well as longwave downwelling irradiance, temperature humidity, etc.

A few of the parameters in the datasets for the month of data are visualized below.

axes = df[['ghi','dni','dhi','lwd','temp_air']].plot(
    subplots=True, legend=False, rot=0, figsize=(8,8), sharex=True)

# Set y-labels and y-limits
axes[0].set_ylabel('GHI [W/m$^2$]'), axes[0].set_ylim(-10,1300)
axes[1].set_ylabel('DNI [W/m$^2$]'), axes[1].set_ylim(-10,1300)
axes[2].set_ylabel('DHI [W/m$^2$]'), axes[2].set_ylim(-10,1300)
axes[3].set_ylabel('LWD [W/m$^2$]'), axes[4].set_ylim(200,500)
_ = axes[4].set_ylabel('Temperature [°]'), axes[4].set_ylim(0,40)

Notice how that they are multiple periods where there is gaps in the irradiance data.