Sentinelhub-js — open-source library for satellite imagery powered web applications
Introducing JavaScript/TypeScript library for seamless integration of Sentinel Hub and other similar EO web services in web or node.js applications.
We are happy to announce the availability of a new opensource JavaScript / TypeScript library, sentinelhub-js
(MIT license). It will join our existing libraries that simplify EO data processing, such as sentinelhub-py
and eo-learn
(both Python). The library is used in production by two well-known remote sensing web applications (EO Browser and Sentinel Playground) and we are in the process of migrating other applications too.
Why is this big news? sentinelhub-js
allows web developers to easily access remote sensing data and to integrate it with their applications — no need to construct queries using fetch
, axios
and similar anymore. The library is not limited just to the Sentinel Hub service either, it allows integration of any remote sensing service which supports standard OGC queries.
In other words, the goal of the library is to provide a simple, unified JavaScript interface to multiple Earth Observation (EO) services. All datasets are treated similarly in a sense that a set of common operations is provided for each of them, but user can still use dataset-specific functionality where available.
This post tries to provide an introduction to the library as it exists at the time of writing (27th of March 2020). As the library is being developed actively, please consult sentinelhub-js repository for installation instructions and up-to-date documentation.
We hope that this library will help developers build applications that will help bring field of remote sensing closer to end users. These application will join existing apps such as opensource EO Browser and Sentinel Playground, which can already serve as a starting point for any application developer working on satellite imagery tool.
Layer
The core concept in this library is that of a “layer”. Layer has all the information about the satellite data that will be used — which dataset is used (including its infrastructure location), which combination of bands is used, and any other dataset-specific filter parameters, such as orbit direction, acquisition mode, polarization, maximum cloud cover and similar.
Constructing layers manually
To create a new layer, we can use one of the …Layer
classes, for example WmsLayer
:
To get the WMS URL / instance ID, and to create your own layers, Sentinel Hub Dashboard should be used. If you don’t have an account yet, sign up — there is a free trial available.
WmsLayer
allows using any dataset on any service that supports the OGC WMS standard. However Sentinel Hub provides additional capabilities which are not accessible through WmsLayer
. To use them, we must create dataset-specific layers. For example, here’s how you create a layer for Sentinel-2 L2A:
There are dataset-specific classes available for every dataset that Sentinel Hub service supports, including:
S1GRDAWSEULayer
andS1GRDEOCloudLayer
(Sentinel-1 on AWS and on EO Cloud infrastructure respectively)S2L1CLayer
andS2L2ALayer
(Sentinel-2 L1C and L2A)S3OLCILayer
andS3SLSTRLayer
(Sentinel-3 OLCI and SLSTR)S5PL2Layer
(Sentinel-5P)EnvisatMerisEOCloudLayer
(Envisat MERIS)BYOCLayer
(Bring Your Own Data/COG)Landsat5EOCloudLayer
,Landsat7EOCloudLayer
,Landsat8EOCloudLayer
andLandsat8AWSLayer
(Landsat 5, 7 and 8 on EO Cloud infrastructure, and Landsat 8 on AWS)MODISLayer
(MODIS)DEMLayer
(Digital Elevation Model)
For access to other remote sensing services WmsLayer
should be used.
Constructing layers by querying service
It is also possible to construct multiple layers at once with LayersFactory.
This method uses WMS GetCapabilities
request to get the information about the layers from service, and then constructs the appropriate objects automatically. Factory method LayersFactory.makeLayers
returns an array of …Layer
objects with all the available parameters set:
To avoid constructing unnecessary layer objects, we can also filter them:
Searching for available satellite data
Before we can display data, we need to know the times at which the data is available, given the dataset and our area of interest (bounding box).
Note: special care must be taken when using times. As is usual, all communication with services uses UTC times. However, the common representation of dates in JavaScript is a Date
object, which doesn’t support setting a custom (non-local) timezone — even if constructed with new Date(Date.UTC(…))
, the result is a Date
object in the local timezone. This means that when interacting with the library, all times (parameters for the functions and the returned results) are represented as Date
objects (again, always in local timezone). If your application needs to work with times in UTC (as is often the case), it needs to convert these Date
objects from/to UTC. For example, if using moment.js
:
Layers support three methods that allow searching for available data:
findTiles()
findDatesUTC()
findFlyovers()
These functions allow searching either for times of the individual tiles, for dates, or for flyovers — parts of orbits over a given area.
For example, function findFlyovers
returns an array of time intervals. Each time interval tells us when the satellite started collecting data over the specified area, and when it has exited the area. The code says it best:
Fetching satellite images
Once we have a layer instance, we can fetch satellite images using getMap
or getMapUrl
methods. First we need to specify the parameters such as area, time frame, output format and similar:
If the data is not available for the specified bounding box and time range, you will not get an error — the result will be an empty image (transparent or single color, depending on the layer definition and output format). Similarly, if the time range includes multiple orbits, they will be merged together (stacked on top of each other).
With that, we can get the image binary data. In a browser, data is returned as Blob
, while in node.js a string is returned:
There are different ways we can use this data, for example we can display it in an <img>
DOM element (browser) or save the image to disk (node.js).
If we have selected a Sentinel-2 L2A “true color” layer, the resulting image looks like this:
Up until now we have only used WMS, but this library also supports the Sentinel Hub Processing API. To use it, you need to authenticate first.
Access credentials (
clientId
andclientSecret
) should be retrieved from Sentinel Hub Dashboard by creating a new OAuth client.
Once we are authenticated, we call getMap
with ApiType.PROCESSING
parameter. The content of the resulting image should be exactly the same as when using WMS:
We can also get just the URL of the image, if the API supports HTTP GET:
getMapUrl
method will only work with the WMS API, because the Processing API uses HTTP POST method which can’t be represented by an URL. However a benefit of POST requests is that the request is not limited in size, as is the case with GET. Side note: Processing API also supports additional functionalities like data fusion (not yet available through this library — coming soon!).
Final thoughts
We are very excited about this library and hope you will find it as useful as we do. Even though the library is young, we do not anticipate any breaking changes happening anytime soon. We do have quite a lot of new functionalities in mind for the coming months. We welcome suggestions, bug reports (or even fixes), feature requests, or any feedback really... :) Use GitHub issues or Sentinel Hub Forum to get in touch with us, we’d be happy to hear from you!