Sentinel Hub forum is the best place to get in touch with support staff as well as other Sentinel Hub

You can find Quick tutorial on Sentinel Hub here.

We also recommend a short course on the fundementals of remote sensing with a comprehensive overview of common use cases and tools. If you want to dive a little deeper into the topics of Sentinel Hub, you can find our webinars here.

You can find the Sentinel Hub forum here. Select your category of interest and you might find your question already answered. If not, ask and our team or other users will help you find a solution.

If you don’t have the EO Browser/Sentinel Hub account yet:

To receive our bimonthly newsletter and stay updated with important news, we invite you to create a new free account here. After choosing desired subscription preferences and enabling the option to receive latest news and information on Sentinel Hub, confirm it by clicking the Sign up button. You will receive the verification email, follow the link in it and stay updated.


If you already have the EO Browser/Sentinel Hub account:

Log in to the Sentinel Hub Dashboard with your credentials (email and password). Choose the User settings tab and enable the option for receiving the latest news under Marketing premissions. Confirm your choice by clicking the Save Changes button.


The newsletters are released every 2 months and are archived on our newsletters page our newsletters page, where you can explore all the news you might have missed.

You can cite our applications / web pages in the following way (link is optional):

When referring to Sentinel data acquired through the Sentinel Hub services, please use the following credit:

  • “Modified Copernicus Sentinel data [Year]/Sentinel Hub”

To delete your profile and remove your personal information from our web page, go to the Sentinel Hub Dashborad. Under the "User settings" tab click on "Delete profile" button and confirm your decision by clicking one more time on "Yes, delete profile" button in the pop-up window.

Subscription, Packages and Pricing

Our subscription plans are described here:

The difference between consumer / research and commercial plan is in the purpose of the usage of our services. If you are using the Sentinel Hub services for research purposes or for yourself, consumer / research option is the right one. If you are using it within your company, you should use commercial option.

Mission Product Resolution [m] km2 for one PU € per 1 km2
Sentinel-2 True color 10 26.2 0.00006
NDVI 10 39.3 0.00004
All 13 bands 10 6.0 0.00025
Sentinel-1 VV gamma0 ortho 20 157.3 0.00001
Sentinel-3 OCI True color 300 23 593.0 0.00000007
OTCI 300 35 389.4 0.00000004
Landsat-8 True color - pansharpened 15 44.2 0.00003
NDVI 30 59.0 0.00003

VAT will be charged if you are purchasing our services as:

  • not VAT registered company in the EU
  • an individual from the EU or outside the EU

VAT won’t be charged if you are purchasing our services as:

  • VAT registered company in the EU
  • company outside the EU

Yes. You can go to the Dashboard and choose a recurrent subscription option.

This gives you an option to set-up automatically recurrent payment by PayPal or credit card, which you can cancel at any time.

Generally we advise to subscribe for an annual package as it comes with a discount.

To pay for the Sentinel Hub services you can choose between the following options:

  • PayPal
  • credit card (all supported by Adyen)
  • wire-transfer

If you decide to subscribe, go to the Dashboard and choose one of the plans.

To change your payment method, two steps are needed:

  1. You have to revoke existing subscription, which you can do in the Sentinel Hub Dashboard under the Billing tab / Order History. More details on how to revoke a subscription are described here. Your account will remain active until one month after the last payment.

  2. Before your account expires, you have to establish a new subscription with your prefered payment method in the Sentinel Hub Dasboard under the Billing tab / Plans.

You can cancel your subscription to the Sentinel Hub services in the Sentinel Hub Dashboard. The link will take you to the "Billing" tab and the "History" list. Click on the link to "Details" of your subscription you would like to cancel. Click on the "Revoke subscription" button and confirm your choice. Your status will be changed to "revoked" and subscription canceled.

If you decide to cancel, you'll be able to access Sentinel Hub's premium features until the end of your current billing cycle. We don't issue refunds.

No price plan is activated in a trial stage.

Please note that Sentinel Hub trial account is not allowed for commercial use. After 30 days, you can choose the subscription service you want and subscribe. There is no automatic payment.

The differences in functionality or data between the trial account and the subscription account:

  • The trial account is limited to 30,000 requests and 300 processing units per minute, while subscription accounts have higher limits. See our pricing packages for details.
  • The trial account does not provide access to TPDI functionality (commercial data). For this, you need one of the subscription accounts.
  • The tiral account does not provide access to the batch API. For this, you need one of the Enterprise packages.

If you need higher throughput during the trial period, contact us.

The trial use is completely free and there will be no costs associated to it whatsoever. You do not need to cancel your account after the trial period expires, and there are no automatic charges.

After 30 days of the trial period:

  • The access to OGC services will expire, but you will still be able to use EO Browser for non-commercial purpose.
  • To continue using OGC services you will have the ability to subscribe to one of the plans directly in the Sentinel Hub Dashboard.

We do not charge anything automatically, nor do we extend a subscription period automatically. A week before the end of subscription period you will be notified about incoming event and asked, whether you would like to extend the subscription. In case your decide for an extension, you will be asked for additional payment. In the opposite case, account will be frozen for one month period and deleted afterwards.

If you decide for extending the subscription, go to the Dashboard and choose one of the plans.
This gives you an option to set-up automatically recurrent payment by PayPal or credit card, which you can cancel at any time.

Yes! There are ESA sponsored accounts available. Visit our website on the Network of Resources for a step-by-step guide on how to apply!

You can find example mobile app here.

Note that the subscription option does not include the mobile app itself. This is simply an option of the service best suited for integration in various apps.

A definition of a processing unit is avaliable in our documentation. The rules with examples of how to calculate the number of processing units for a request are also provided.

Individual subscription is meant for one, named user. She or he can use it at any device but this account cannot be shared amongst different users.

Maxar WorldView data are available to customers from the following countries:

Albania, Algeria, Andorra, Armenia, Austria, Azerbaijan, Belarus, Belgium, Bosnia and Herzegovina, Bulgaria, Croatia, Cyprus, Czech Republic, Denmark, Egypt, Estonia, Finland, France, Georgia, Germany, Greece, Hungary, Iceland, Ireland, Israel, Italy, Kosovo, Latvia, Liechtenstein, Lithuania, Luxembourg, Macedonia, Malta, Moldova, Monaco, Montenegro, Morocco, Netherlands, Norway, Poland, Portugal, Romania, San Marino, Serbia, Slovakia, Slovenia, Spain, Sweden, Switzerland, Tunisia, Turkey, Ukraine, United Kingdom, Vatican City.

Customers have access to full and global archive.

In a nutshell

You subscribe to a part of the land (i.e. agriculture parcel) and get, for a period of one year, access to all available PlanetScope data in that area - both archive and fresh data. This subscription model is perfect for agriculture and other continuous monitoring use-cases.

More details

  • The price of the annual subscription depends on the country, where one wants to download the data from. See Billing for more information about Tiers.
  • Users can purchase a quota in packages of 100 hectares for each of the Tiers. This quota can be consumed for several dislocated areas (parcels), each area having the minimum size of 1 hectare.
  • Subscription period starts at the time of the first purchase and lasts for 12 months since then.
  • In case the User requires additional quota, they can purchase it at any time during the year ("Top-up"). Consecutive purchases are co-termed with the original purchase (price is proportional to the remaining period). During the last three months of the suscription period, it is required to subscribe for one additional year.
  • In case the User consumes more data than they have subscribed to, there is a 20% overage fee. We therefore kindly recommend to purchase the quota up-front.
  • The total "area under management" is defined as "the area of union of all polygons used in the orders within a period of one year".

Follow up questions

Q: If I order the data for a polygon A today and then once again for the same polygon a week from now. Do I consume quota twice?
A: No. As long as you are fetching the data from the same polygon, you will only consume once the area of the polygon.

Q: If I order the data for polygon A today, then increase the polygon a bit (polygon A'). How much quota will I consume?
A: As long as the polygon A is fully within polygon A', you will consume the total area of polygon A' ("union of polygons" rule)

Q: If I purchase 100 hectares today and another 100 hectares in 6 months, how much will I pay?
A: Your first purchase will be for the full price, second one with 50% discount (as it will only cover the period of 6 months).

Available EO Data

Sentinel-2 - global coverage, full archive
Sentinel-3 - global coverage, full OLCI archive
Sentinel-1 - global coverage, full GRD archive
Sentinel-5P- global coverage
Landsat-8 USGS - global coverage, almost full archive
Landsat-5, 7 and 8 - ESA Archive - Europe and North Africa, full archive
ENVISAT MERIS - global coverage, full archive
Digital Elevation Model – DEM - a static data collection based on MapZen’s DEM updates
MODIS - Terra and Aqua

For more details check also our list of available data collections on our web page.

To explore availability, please check EO Browser, and Sentinel Playground (for DEM).

To browse various data, go to EO Browser. Read about how to use it here.

We have our services installed on several places to get fastest access to the data. This is why there are different access points for different data collections. To learn which configurator you should use to configure your own configurations and layers, or which endpoints to use with OGC or Process API, visit our page on data collections or our documentation for more details.

We put a lot of effort to make data available as soon as possible. However, we depend almost entirely on how fast the data provider can process and disseminate the data.

For Sentinel products, ESA usually makes them available on their OpenHub in 6-12 hours (target timing is 3-6 hours, sometimes it takes longer, even more than one day). We instantly pull data down but as it takes some time to download complete data, it might take up to one additional hour before they are available on Sentinel Hub.

The best way to get information about all the available scenes in a specific area is to use our Catalog service API, which will give you detailed geospatial information for each tile, that you can control by specifying fields, limits and other properties. For this specific use case, it is most useful to use the `distinct` parameter with `date`, which will return a list of the available dates for your requested BBOX and time range. To make this Catalog API request, import the following CURL request to Postman. You will need to authenticate the request with a token.

curl -X POST '' \
-header 'Authorization: Bearer <your access token>' \
-header 'Content-Type: application/json' \
-data-raw '{
    "bbox": [13,45,14,46],
    "datetime": "2019-12-10T00:00:00Z/2020-12-15T00:00:00Z",
    "collections": ["sentinel-1-grd"],
    "limit": 50,
    "distinct": "date"

In the curl request above, the first line is the URL for the request, that you only need to change if you’re using data collections on different deployments. The first header is where you add your access token; if you authenticate the collection or the request in Postman, the token will be automatically added. The second header is where you specify the desired output, which in this case, is a JSON file. In data-raw, you will specify the bbox, time range (datetime), data collection (collections), limit (the upper limit of the number of results), and with the line "distinct":"date", you will limit your results to only include information on the acquisition date. Consult the Catalog API reference to learn more about the available parameters.

The result for the CURL request above will look like this:

    "type": "FeatureCollection",
    "features": [
    "links": [
            "href": "",
            "rel": "self",
            "type": "application/json"
    "context": {
        "limit": 50,
        "returned": 4

At the beginning of the result, you can see all the available dates listed for your request.

It’s also possible to search the available scenes using OGC WFS request, which might be a bit easier to use, but gives you much less search control.

To make a WFS request, you will need to add your INSTANCE_ID, specify the bbox, timerange (TIME), data collection (TYPENAMES), coordinate system (srsName) and a request type. Read more on the parameters here. An example WFS request would look like this:,5039853,3244050,5045897&TIME=2019-02-11/2019-02-12

You can test the WFS examples with different parameters and inspect the results instantly here.

Note that you can also use MAXCC parameter (maximum cloud coverage) in this call to filter for cloudless data.

Use FEATURE_OFFSET parameter to control the starting point within the returned features and MAXFEATURES parameter the maximum number of parameter of features to be returned by a single request.

As a result you will get a list of all the available scenes for the chosen location in JSON format (or XML if set so). Some of the dates may be duplicated if there are two scenes available in the area. You should simply ignore these duplications.

In Sentinel Hub, the calculated and output values depend on what users specify in their evalscripts (or custom scripts). By calculated values we are referring to the values that are returned from the evaluatePixel() function or from a simple script. Output values are values returned from Sentinel Hub, after the calculated values go through formatting defined by sampleType. In the evalscript, calculated and output values are controlled by:

  • In the setup() function, the requested bands and units define what values are used as input for the calculation (in simple scripts, default units are used). For example, if Sentinel–2 band B04 is requested in REFLECTANCE, the input values will be in the range 0–1. If Sentinel–2 band B04 is requested in DN (digital numbers), the input values for the calculation will be in the range 0–10000. Typical value ranges can be found in our data documentation, chapter Units for each data collection.
  • The evaluatePixel() function defines the actual calculation (in simple scripts, the entire script is its equivalent). Sentinel Hub uses double precision for all calculations and rounds only the final calculated values before they are outputted.
  • The value of the sampleType parameter in the setup() function define the format of the output values. Possible values are AUTO, UINT8, UINT16 and FLOAT32. See our sampleType documentation for more details. When the sampleType is not specified (e.g. in simple scripts), the default value AUTO will be used. sampleType.AUTO takes calculated values from the interval 0–1 and stretch them to 0– 255. If your calculated values are not in the range 0–1, make sure you either scale them to this range in the evaluatePixel() function or specify another sampleType.

Example 1: NDVI

In this example, we want to output values of the NDVI index, calculated based on Sentinel–2 data. Our evaluatePixel() function is:

function evaluatePixel(sample) {
    let NDVI =  (sample.B08 – sample.B04)/( sample.B08 + sample.B04)
    return [NDVI]

The requested units in this example do not have any influence on the calculated values of the NDVI. The output values returned by Sentinel Hub (black values in the table) for different sampleTypes are:

Calculated Value sampleType.AUTO sampleType.UINT8 sampleType.UINT16 sampleType.FLOAT32
-1 0 0 0 -1
0 0 0 0 0
0.25 64 0 0 0.25
1 255 1 1 1

Use sampleType:“FLOAT32” to return full floating -1 to 1 values. See the example here.

If you do not need values, but a vizualization, you can use sampleType:“AUTO”, but make sure to either:

  • map the NDVI values to the 0–1 interval in the evaluatePixel() function, e.g.:

    function evaluatePixel(sample) {
        let NDVI =  (sample.B08 – sample.B04)/( sample.B08 + sample.B04)
        return [(NDVI+1)/2]
  • use a visualizer or a color visualization function, e.g. valueInterpolate.

Example 2: Sentinel–2 band B04

In this example, we want to output raw values of Sentinel–2 band 4. Our evaluatePixel() function looks like this:

function evaluatePixel(sample) {
     return [sample.B04]

If we request units: “REFLECTANCE”, the output values returned by Sentinel Hub (black values in the table) for different sampleTypes are:

Calculated Value sampleType.AUTO sampleType.UINT8 sampleType.UINT16 sampleType.FLOAT32
0 0 0 0 0
0.25 64 0 0 0.25
0.5 128 1 1 0.5
1 255 1 1 1
1.05 255 1 1 1.05

If we request units: “DN”, the output values returned by Sentinel Hub (black values in the table) for different sampleTypes are:

Calculated Value sampleType.AUTO sampleType.UINT8 sampleType.UINT16 sampleType.FLOAT32
0 0 0 0 0
2500 255 255 2500 2500
5000 255 255 5000 5000
10000 255 255 10000 10000
10500 255 255 10500 10500

Example 3: Brightness Temperature Bands

Here we output a Sentinel–3 SLSTR band F1 with typical values between 250–320 representing brightness temperature in Kelvin. The evaluatePixel() function is:

function evaluatePixel(sample) {
    return [sample.F1]

The output values returned by Sentinel Hub (black values in the table) for different sampleTypes are:

Calculated Value sampleType.AUTO sampleType.UINT8 sampleType.UINT16 sampleType.FLOAT32
250 255 250 250 250
255 255 255 255 255
275.3 255 255 275 275.3
320 255 255 320 320

Use sampleType:“FLOAT32” to return original values. If integer values are still acceptable for your application, use sampleType:“UINT16”.

If you do not need values but a vizualization, you can use sampleType:“AUTO”, but make sure to either:

  • map the values to the 0–1 interval in the evaluatePixel() function, e.g.:

    function evaluatePixel(sample) {
        return [sample.F1/320]
  • use a visualizer or a color visualization function, e.g. valueInterpolate.

Yes, the atmospherically corrected Sentinel-2 L2A data is available globally since 2017. For Europe it is available since 2015. For more information about S2L2A visit our atmospheric correction page and our documentation.

Some areas never have cloud coverage below 20%. This is why in Playground, where we have default setting for 20% of cloud coverage, for some areas seems there is no satellite imagery available. However if we turn slider for maximum cloud coverage to 100%, we can see data available.

We would like to serve data as they are, without uncontrolled changes, because it is almost impossible to set color balance to one fitting all places in the world and all groups of users. You can still tweak contrast in several ways.

Figure 1: Raw picture.

You can tweak "Gain" (brightness) to automatically equalize the image.

Figure 2: Gain adjusted to desired values.

You can tweak "Gamma" (contrast) as well.

Figure 3: Gamma adjusted to desired values.

Use the atmospheric correction by using the S2L2A atmospherically corrected data instead of S2L1C. As you can see on the image below, atmospheric correction increases the contrast, as it corrects for the effects of the atmosphere.

Figure 4: Atmospheric correction with S-2 L2A.

Source Data Using the WFS Request

To access metadata of the scene or to see which tiles are available, use the WFS request. Get started by checking out the WFS use examples.

Source Data Using the WFS Request on S3

In case one needs, for a specific purpose, source data used for some scene, he can use a WFS request with the same parameters as for WMS. A response will contain a path attribute, e.g. something along the lines of:

"path": "s3://sentinel-s2-l1c/tiles/310/S/DG/2015/12/7/0"

It is then possible to access these data from AWS, where they are stored by adding relevant filenames, see typical structure of a typical scene at AWS bellow.

In case you want to download it from outside of AWS network, you can change the address to:

Typical structure of the scene:

 aws s3 ls s3://sentinel-s2-l1c/tiles/10/S/DG/2015/12/7/0/
                           PRE auxiliary/
                           PRE preview/
                           PRE qi/
2017-08-27 20:39:26    2844474 B01.jp2
2017-08-27 20:39:26   83913648 B02.jp2
2017-08-27 20:39:26   89505314 B03.jp2
2017-08-27 20:39:26   97645600 B04.jp2
2017-08-27 20:39:26   27033174 B05.jp2
2017-08-27 20:39:26   27202251 B06.jp2
2017-08-27 20:39:26   27621995 B07.jp2
2017-08-27 20:39:26  100009241 B08.jp2
2017-08-27 20:39:26    2987729 B09.jp2
2017-08-27 20:39:26    1218596 B10.jp2
2017-08-27 20:39:26   27661057 B11.jp2
2017-08-27 20:39:26   27712884 B12.jp2
2017-08-27 20:39:26   27909008 B8A.jp2
2017-08-27 20:39:26  134890604 TCI.jp2
2017-08-27 20:39:26     379381 metadata.xml
2017-08-27 20:39:26     166593 preview.jp2
2017-08-27 20:39:49     106056 preview.jpg
2017-08-27 20:39:47       1035 productInfo.json
2017-08-27 20:39:26       1678 tileInfo.json

We put quite a lot of effort into leaving the data as they are, not to modify it. However, this also means that some data mistakes get to our users. One of these is geolocation shift.

There is a nice blog post written by CNES colleague Olivier Hagolle on this topic. We suggest to read it and send a notice to ESA and Copernicus to do something about it

Sentinel Hub currently supports Airbus Pleiades, Airbus SPOT, Planet PlanetScope and Maxar WorldView/GeoEye commercial data collections. Due to a different licensing model, we cannot provide free access to these data collections. One therefore first has to purchase the quota for any of the constellations and order the image through us (most commonly an on-going monitoring of specific area on daily/weekly/monthly basis). Once this order is processed, we will make the purchased data available through Sentinel Hub services in the same manner as other data.

See our Commercial Data Webinar, where you will learn all about commercial data in Sentinel Hub. It goes into detail on where to find all the relevant documentation, how to order data (including time-series data) and visualize it, view statistical information, import data into your own GIS and get it sponsored by the Network of Resources. See also our PDF tutorial on how to search, order and visualize commercial data in Requests Builder and Postman.

If you’re conducting research or precommercial exploitation, you can get commercial data sponsored by applying to the ESA’s Network of Resources. To help you apply, we have prepared a step by step guide on how to submit the proposal.

EO Browser

Simply write coordinates in the “Search places” tool in “lat,lon” form, e.g.:


And click enter

As EO Browser timelapse functionality has a limit of processing up to 300 images at once, we need to do some post-processing, to be able to create longer timelapses. This can be especially useful with data collections like MODIS, with data available all the way back to the year 2000. Take a look at this MODIS timelapse of the Aral sea, dating from 2002 to 2019.

First, use command prompt to convert .gif timelapses from EO Browser into .mp4 files and then merge them together. For example, if we want to create an 18 years long timelapse, six timelapses, each three years long, are required. You should first download your smaller timelapses from EO Browser.

After downloading the gifs from EO Browser, we should transform them into .mp4 files. To do so, we first need to download and install ffmpeg program for making videos. Follow this tutorial to install ffmpeg.

To test if ffmpeg is installed, go to CMD and type: ffmpeg -version.

To transform a gif into mp4, first navigate to the folder where your gif files are stored, then open your command prompt and write in the following code:

ffmpeg -i GIF1.gif -movflags faststart -pix_fmt yuv420p -vf "scale=trunc(iw/2)*2:trunc(ih/2)*2" GIF1vid.mp4

The only part of the code you need to change is the name of your gif at the start and the name of the output .mp4 video at the end.

You need to transform all your .gif timelapses into separate .mp4 files:

ffmpeg -i GIF1.gif -movflags faststart -pix_fmt yuv420p -vf "scale=trunc(iw/2)*2:trunc(ih/2)*2" GIF1vid.mp4<br>
ffmpeg -i GIF2.gif -movflags faststart -pix_fmt yuv420p -vf "scale=trunc(iw/2)*2:trunc(ih/2)*2" GIF2vid.mp4<br>
ffmpeg -i GIF3.gif -movflags faststart -pix_fmt yuv420p -vf "scale=trunc(iw/2)*2:trunc(ih/2)*2" GIF3vid.mp4

Finally, merge all the .mp4 files into a final .mp4 file with the following code:

ffmpeg -i GIF1vid.mp4 -i GIF2vid.mp4 -i GIF3vid.mp4 -filter_complex "[0:0] [1:0] [2:0] concat=n=3:v=1:a=0" FinalVideo.mp4

In this code, we specify the output name of the final .mp4 timelapse and list the .mp4 files we want to merge. We preface the .mp4 files with -i. Then we need to add as many arrays, as there are input .mp4 videos; [0:0] for the first one, [0:1] for the second one, [0:3] for the third one and so on. The n=3 indicates how many input .mp4 files there are.

For 6 input .mp4 files, the code would look like this:

ffmpeg -i GIF1vid.mp4 -i GIF2vid.mp4 -i GIF3vid.mp4 -i GIF4vid.mp4 -i GIF5vid.mp4 -i GIF6vid.mp4 - filter_complex "[0:0][1:0][2:0][3:0][4:0][5:0] concat=n=6:v=1:a=0" FinalVideo.mp4

When you create a custom layer in Sentinel Hub Configuration Utility it is possible to select that layer in EO Browser. To do that, first select your configuration on Search tab, then select the appropriate search result, and in Visualization tab select the said custom layer.

However such layers usually contains color visualization (RGB) of values. Because Feature Info Service operates on the indicator values themselves (and not on RGB), that means that you must add an additional layer (in Sentinel Hub Configuration Utility) which returns the value without conversion to color. The name of this layer must be constructed from the ID (not name) of the visualization layer:


That is: double underscore, followed by "FIS", followed by another underscore, followed by original layer's ID. For example, if we would like to use Feature Info on a layer with ID "3-NDVI2", we should add a layer with ID "__FIS_3-NDVI2".

The data processing script in the newly added "FIS layer" should either:

  • return a single indicator value or
  • return two values, the last of which indicates cloud coverage (1 if the point is covered by the cloud, 0 if not).

Example data processing script:

function index(x, y) {
    return (x - y) / (x + y);

const ndvi = index(B08, B04);
return [ndvi];

Example data processing script with cloud coverage:

function index(x, y) {
    return (x - y) / (x + y);

const NGDR = index(B03, B04);
const bRatio = (B03 - 0.175) / (0.39 - 0.175);

const isCloud = bRatio > 1 || (bRatio > 0 && NGDR > 0);
const ndvi = index(B08, B04);
return isCloud ? [ndvi, 1] : [ndvi, 0];

Note that this answer is specific to EO Browser and the way it uses layers.

To view your collection in EO Browser, you first need to create a new configuration with visualization layers. To follow the steps below, you will need a Sentinel Hub account and a collection ID. Your collection ID is located in your tab of the configuration utility, where all your collections with ingested tiles are located. There are also some public collections available on our GitHub, where the collection ID can be found for each of them.

Check out how you can find your collection ID by expanding the GIF demonstration below:

Click on the GIF to expand it.

1. Create a new configuration

1.1. Without a template

  • Copy your collection ID to clipboard and go to the tab.
  • Click on the button.
  • Choose a name for your configuration and click on the green button to submit.
  • When the configuration is created, you will see an empty configuration. Continue to the section 1.3 to create a new layer.

1.2. With a template

BYOC templates with preprepared visualization layers are available for commercial data (Airbus Pleiades, Airbus SPOT and PlenetScope) and some publically avaliable collections.

  • Copy your collection ID to clipboard and go to the tab.
  • Click on the button.
  • Choose a name for your configuration and select the optional configuration template matching your data (e.g. Airbus Pleiades Template or Sentinel-2 L2A 120 m Mosaic).
  • When done, click the button to submit.
  • When the configuration is created, you will see a couple of layers already prepared. Click the expand arrow next to each layer title, to see the additional information.
  • You will see that the source is set to Bring Your Own COG and the Collection ID field displays a string of zeroes. Replace this string with your collection ID for each layer in your configuration.
  • Save all your changed layers by clicking on the button next to each layer.

Click on the GIF to expand it.

1.3. Create a new layer

  • In your configuration, click on the button.
  • Choose the name for your layer and set the source to be Bring Your Own COG.
  • Setting the source to Bring Your Own COG will enable the Collection ID field, which will be empty. Enter your collection ID into this field.
  • Click on the pencil icon next to Data Processing, to open the scripting window.
  • For BYOC, no data products are available. You will have to write a visualization script into the window on the right. To do so, you need to know which bands are available for your ingested data and their names. If your data is of the constellation supported by Sentinel Hub (e.g. Sentinel-2, Landsat 8, DEM), you can find band information and example evalscripts on our data documentation and on our custom script repository.
  • When your evalscript is inserted, submit it by clicking on the button. Note that evalscript is a requirement of Sentinel Hub, as it tells the system how to visualize your data.
  • When done, click on the button, to save your layer settings.

Click on the GIF to expand it.

2. Visualize Your Configuration in EO Browser

  • Open EO Browser and click on the login button on the top right, to login to your Sentinel Hub account.
  • Expand the dropdown menu located under Theme on top. Find your configuration by name and select it.
  • Toggle on the data collections found under Data Sources. For BYOC, the offered data collection will usually match the name of your configuration or visualization layers.
  • On the map, zoom to the area where your tiles are ingested and select a time range, that includes the acquisition time of your ingested tiles.
  • If you are unsure what the ingestion dates and locations for your tiles are, check it out on GitHub if you’re working with a public collection, or click on the tile in your collection in the Bring Your Own COG section of the Dashboard. See how to do so here (20:38 - 21:00).
  • When done, click the button.
  • If your search parameters are set correctly, you should see your tiles listed in search results and they should appear on the map. To select one of your tiles, click the button.
  • Your data will be visualized with the layers from your configuration. Feel free to explore them. To learn more about what you can do with your data in EO Browser, visit our EO Browser page.

Click on the GIF to expand it.

If you are trying to get raw data directly in EO Browser following the SciHub link shown below, please note that SciHub is a 3rd party service operated by Copernicus and you need to have a separate account there.

You can create it for free here:

EO Products

We recommend to check our “EO Products” page as well as Index DataBase, which holds numerous descriptions, along with scientific articles.

You can easily create a new EO product in the Configuration Utility.

  1. Create a new configuration or open an existing one.
  2. Click on "Add new layer".
  3. Enter the title of the layer.
  4. Click the "pencil icon" next to Data Processing option to select a predefined product or enter your processing script.

  1. Choose from the available Base Products. See also the available custom scripts for each data source in our repository.
  2. Click on the selected product under Visualization Options and the "Copy Script to Editor" button.
  3. Edit the selected base script in the Custom script editor and click the "Set Custom Script" button when you are done.
  4. Click "Save" under the newly added layer to complete the creation of a new layer.
  5. The newly added layer will appear in the list of layers under your configuration.

For detailed information about WMS configurator click here.
Read also more information about custom scripting.

To learn more about how to create a new configuration, a new layer with data products and a new layer with a custom script from the repository, watch our OGC API with QGIS integration webinar.

There are several ways you can view the Normalized Difference Vegetation Index (NDVI).

You can view it directly in EO Browser, which provides the NDVI visualization as one of the default visualizations.

You can create a new NDVI layer yourself with custom modifications in Configuration Utility, and view it in EO Browser after logging in with your credentials. Read more about creating a new layer and visit our custom scripts repository for more variations of NDVI.

You can also integrate the NDVI layer with the WMS in your own application. Read more about the WMS request, OGC example requests and watch our OGC API with QGIS integration webinar.

When user selects “EO Product template”, she can see the Custom script behind each visualization/processing to make it as transparent as possible on what is happening with the data. We are changing these configurations through time, adding new ones and improving existing ones. For those, who want to ensure that processing of their layers is not changed any more, they can simply edit the original Custom script and gain full control over it.

You can get information from scene classification layer produced by Sen2Cor, for data where S2A is available. Data can be retrieved by identifier “SCL” (e.g. instead of return [B02]; for blue color one can use return [SCL/10];).
Data can be then used for e.g. validation of the pixel value, e.g. along the lines:

          var scl = SCL;
          if (scl == 0) { // No Data
            return [0, 0, 0]; // black
          } else if (scl == 1) { // Saturated / Defective
            return [1, 0, 0.016]; // red
          } else if (scl == 2) { // Dark Area Pixels
            return [0.525, 0.525, 0.525]; // gray
          } else if (scl == 3) { // Cloud Shadows
            return [0.467, 0.298, 0.043]; // brown
          } else if (scl == 4) { // Vegetation
            return [0.063, 0.827, 0.176]; // green
          } else if (scl == 5) { // Bare Soils
            return [1, 1, 0.325]; // yellow
          } else if (scl == 6) { // Water
            return [0, 0, 1]; // blue
          } else if (scl == 7) { // Clouds low probability / Unclassified
            return [0.506, 0.506, 0.506]; // medium gray
          } else if (scl == 8) { // Clouds medium probability
            return [0.753, 0.753, 0.753]; // light gray
          } else if (scl == 9) { // Clouds high probability
            return [0.949, 0.949, 0.949]; // very light gray
          } else if (scl == 10) { // Cirrus
            return [0.733, 0.773, 0.925]; // light blue/purple
          } else if (scl == 11) { // Snow / Ice
            return [0.325, 1, 0.980]; // cyan
          } else { // should never happen
            return [0,0,0];

Please note that it makes sense to use this layer only on full resolution as any interpolation based on classification codelist will not produce reasonable results. You should also use NEAREST upsampling/downsampling setting, which you can find in "Advanced layer editor" .

Also please note that this map does not constitute a land cover classification map in a strict sense, its main purpose is to be used internally in Sen2Cor in the atmospheric correction module to distinguish between cloudy pixels, clear pixels and water pixels.

An example of Blinnenhorn, Switzerland (October 14, 2017):

Sentinel-2 L2A, SCL, acquired with EO Browser

Sentinel-2 L2A, true color, acquired with EO Browser

This is a prototype feature and can change in the future releases.

Image Manipulation

If you want to get float values out of the service, you will have to use 32-bit float image type (as uint8 and uint16 types only support integers).

A custom script which will return NDVI values for Sentinel-2 data could be:

    function setup() {
        input: [{
          bands: ["B04", "B08"]
        output: {
          id: "default",
          bands: 1,
          sampleType: SampleType.FLOAT32
    function evaluatePixel(sample) {
      let ndvi = (sample.B08 - sample.B04) / (sample.B08 + sample.B04)
      return [ ndvi ]

You can either save this in Configuration utility or you can pass it as EVALSCRIPT parameter. For the latter the example of the call is:<INSTANCE_ID>?service=WMS&request=GetMap&layers=MY_LAYER&format=image/tiff&maxcc=20&time=

We suggest to also check the FAQ about details of internal calculation.

If one wants to have pixels transparent (or semi-transparent), the following can be done:

  • format=image/png (note that PNGs are larger than JPGs, which might affect download speed)
  • custom script output needs to have 4 channels, fourth one being alpha, e.g. "return[1,0,0,0.5]" for semi-transparent red pixel or "return[0,0,0,0]" for full transparency

E.g. if one wants to have a Hollstein's cloud overview layer shown in a way, that everything except clouds is transparent, she just needs to change

          let naturalColour = [B04, B03, B02].map(a => gain * a);
          let CLEAR  = naturalColour;
          let SHADOW = naturalColour;
          let WATER  = [0.1,0.1,0.7];
          let CIRRUS = [0.8,0.1,0.1];
          let CLOUD  = [0.3,0.3,1.0];
          let SNOW   = [1.0,0.8,0.4];


          let naturalColour = [0,0,0,0];
          let CLEAR  = naturalColour;
          let SHADOW = naturalColour;
          let WATER  = [0.1,0.1,0.7,1];
          let CIRRUS = [0.8,0.1,0.1,1];
          let CLOUD  = [0.3,0.3,1.0,1];
          let SNOW   = [1.0,0.8,0.4,1];

Note that all other outputs need to be 4-channel ones as well.

Instead of WIDTH and HEIGHT parameters one can use RESX and RESY.

E.g. if one adds “RESX=10m&RESY=10m”, the image will be returned in 10m resolution.

REFLECTANCE is physical property of surfaces, equivalent to the ratio of reflected light to incident light (source), with typical values ranging from 0-1. It requires a 32-bit TIFF floating format. To get original reflectance data from the satellite, use the advanced evalscript and set sampleType to FLOAT32. See the evalscript example for a single grayscale band below:

function setup() {
  return {
    input: [{
      bands: ["B04"]
    output: { 
      bands: 1, 
      sampleType: "FLOAT32" 
function evaluatePixel(samples){
    return [samples.B04]

To get the exact original reflectance values, the user must also make sure that the pixels outputted by Sentinel Hub are at exactly the same position and exactly the same size as in the original data. To do so, the users must ensure to:

  • Request a bounding box, which is aligned with the grid in which satellite data is distributed.
  • Request the same resolution as in the original data (note that different bands of the same satellite can have different resolutions. To check the resolutions for each band, see our data documentation).

We suggest to also check the FAQ about how the values are calculated and returned in Sentinel Hub.

There are several options, depending on what you would like to do.

  • You can use a feature info request and point to some location. The response will contain a date field within it.
  • You can use the WFS service with the same parameters as used in your WMS request (e.g. date, cloud coverage). You will get a list of features representing scenes fitting the criteria.
  • You can configure the layer to show acquisition dates. Go to the layer of your choice and follow the steps:
    1. Click the "Advanced" option in the Layer tab to enter advanced parameters dialogue.
    2. (optional) You can turn on Help by clicking on "?" top right.
    3. Add "additionalData" node with type "Date"
    4. Click Save in Advanced parameters dialogue.
    5. Click Save Layer and layer's tab.

Grid of solar zenith angles and grid of solar azimuth angles are accessible by names sunZenithAngles and sunAzimuthAngles, respectively, and can be used in a similar way as band values, e.g.:

  return [sunAzimuthAngles/50]; 
return [sunZenithAngles/60];

There are also two grids named viewZenithMean and viewAzimuthMean that contains average viewing incidence angles (zenith and azimuth) across all bands and detectors. They can be used as, e.g.:

  return [viewAzimuthMean/70];
return [viewZenithMean/80];

Custom Scripts

1. Finding the appropriate satellite scene

  • Search for the location of your interest either by scrolling the map with mouse or enter location in the search field on the right side of your screen.
  • Choose from which satellites you want to receive the data (checkboxes on the left side of your screen).
  • Select maximum Cloud coverage percentage.
  • Select time range by either typing the date or select the date from calendar.

2. In the Results tab choose your candidate satellite image by clicking Visualize button.

3. In the Visualization tab choose Custom (Create custom rendering) button.

4. Open the custom script dialog with clicking on the </> icon.

5. Write your own script or copy custom scripts, which are stored elsewhere, either on Google drive, GitHub or in our Custom script repository. 

In case the script is too long, check this description.

For more information on how to create custom scripts check our Custom Script Tutorial and a friendly video guide.

Custom Script integrates Chrome V8 JavaScript engine, so vast majority of the functions supported there can be used in Custom Script as well. Some of the functions, that can be used with our custom scripts, are described in our Evalscript V3 documentation.

To start creating your own custom scripts, visit our custom scripts page, where you can dive into tutorials, documentation, interesting blogs and start creating your own visualizations.

Add the EVALSCRIPT parameter to your OGC request URL with the value of the base64 encoded script, as such: evalscript=cmV0dXJuIFtCMDQqMi41LEIwMyoyLjUsQjAyKjIuNV0%3D

More on custom scripts described here.

A working WMS request from EO Browser, using a simple custom evaluation script:,B02,B03&evalscript=cmV0dXJuIFtCMDgqMi41LEIwNCoyLjUsQjAzKjIuNV07

Note that the LAYERS parameter is always going to equal B01,B02,B03 when using a PRESET=CUSTOM with a custom evalscript.

Raster calculations are done in custom scripts. You can access custom scripts in Configuration Utility, in each layer under each configuration.

To edit the script, click on the "pencil icon" aside the Data processing option under a selected layer and enter the Custom Script Editor. See more details here.

How to use the script is detailed here.

An example of the NDVI script below and visualized in EO Browser.

// NDVI calculation
let ndvi = (B08 - B04) / (B08 + B04)  
return [ndvi]

Scripts in EO Browser are passed to Sentinel Hub service using "GET request", which is limited in number of characters, depending on the browser used between 1.000 and 4.000.

But there is an easy way to work around this:
1. Upload your script to some publicly accessible web-site, for example GitHub, like we do in Custom Script repository. E.g. LAI script.

2. Select "Use URL" and paste the URL to the script in "Script URL" field

3. Click Refresh

In Configuration Utility, it is possible to edit Data Processing of a Layer and observe live changes in Layer's Preview before even saving the Layer. This feature can be useful for tweaking custom scripts parameters.

Best way to do this is to duplicate a Layer, and open Preview by clicking the "Show preview" button in original and duplicated Layer for easier comparison. Edit one of them to see changes between scripts by opening the Layer's "Data Processing" settings with clicking on the "Pencil" button. After the appropriate EO product is chosen hit the button "Copy script to editor" to tweak the script. After setting the custom script you can immediately inspect the changes in the preview window without saving the Layer.

You can also choose different EO Products under "Data processing settings".

With hitting the  button you will reset the layer.

Please note that this doesn't work for the data collections which are not included in the Sentinel Playground application, such as Sentinel-5P, Sentinel-3, Landsat 5, 7 and others.

By employing the dynamically interpreted JavaScript language, and providing some specialized functions you can combine the bands of multispectral satellite data in unprecedented ways.

Here is an example how to tweak the image with a custom script in case of volcano eruption:

return [
  B04 * 2.5 + Math.max(0, B12 - 0.1),
  B03 * 2.5 + Math.max(0, B11 - 0.1),
  B02 * 2.5

Erupting vulcano

Etna volcano eruption, dated 16. 3. 2017. Image combined from true colour image, overlaid with SWIR bands 11 and 12. (view on Sentinel Playground)

You can find more examples and how to tweak the images for easier detection of Earth surface changes, clouds, snow, shadow, water etc. in our blog post.

Use the colorBlend method:
colorBlend(inputValue, indexArray, outputValueArray) The returned value is interpolated between the two consecutive values in outputValueArray (which represent RGB colors normalized to [0,1], e.g. pure red is [1,0,0]) based on the inputValue's location in the indexArray.

Note the indexArray and outputValueArray must be the same size. For example: return colorBlend(B04,    [0, 0.2, 0.4, 0.6, 0.8, 1],    [[0,0,0], [0.1,0.2,0.5], [0.25,0.4,0.5], [0.4,0.6,0.5], [0.75,0.8,0.5], [1,1,0.5]]); If B04 is 0.25 it will interpolate between [0.1,0.2,0.5] and [0.25,0.4,0.5] since they are the corresponding colors to the 0.2 and 0.4 indices in the indexArray nearest to B04.

You can use Custom scripts and type in-the code along the following lines:


function stretch(val, min, max)  {
  return (val-min)/(max-min);
return [
  stretch(B04, 0.05, 0.5),
  stretch(B03, 0.05, 0.5),
  stretch(B02, 0.05, 0.5)]

Upsampling and downsampling define the method used for interpolation of the data on non-natural scales. E.g. resolution of Sentinel-2 data (R,G,B and NIR bands) is 10 meters but in some occasions you would want to look at the data with higher scale (e.g. at 1 m pixel resolution) or lower scale (e.g. 1000 m pixel resolution). 
A default option is "nearest neighbour", which is best for performance. "Bicubic" is often nicer  on higher scales.
Note that the data are always exactly the same - it is just the interpolation method.

An example of the NDVI image of the field:


True color pansharpening can be implemented in Custom script in the following way:

weight = (B04 + B03 + B02 * 0.4) / 2.4;
if (weight == 0) {
  return [0, 0, 0];
ratio = B08/weight * 2.5;
return [B04*ratio, B03*ratio, B02*ratio];

If one wants to pansharpen just RED band, it goes along the similar way:

weight = (B04 + B03 + B02 * 0.4) / 2.4;
if (weight == 0) {
  return [0, 0, 0];
ratio = B08/weight * 2.5;
return [B04*ratio];

The Landsat Collection 1 Level-1 Quality Assessment (QA) 16-bit band, as defined at, contains unsigned integers that represent bit-packed combinations of surface, atmospheric, and sensor conditions that can affect the overall usefulness of a given pixel.

Designated fill, terrain occlusion and cloud values represent if a condition exists:

- 0 = This condition does not exist
- 1 = This condition exists

Radiometric saturation represent how many bands contain saturation:

- 0 = No bands contain saturation
- 1 = 1-2 bands contain saturation
- 2 = 3-4 bands contain saturation
- 3 = 5 or more bands contain saturation

Cloud confidence, cloud shadow confidence, snow ice confidence and cirrus confidence represent levels of confidence that a condition exists:

- 0 = “Not Determined” = Algorithm did not determine the status of this condition / "No" = This condition does not exist
- 1 = “Low” = Algorithm has low to no confidence that this condition exists (0-33 percent confidence)
- 2 = “Medium” = Algorithm has medium confidence that this condition exists (34-66 percent confidence)
- 3 = “High” = Algorithm has high confidence that this condition exists (67-100 percent confidence

These values can be obtained using utility function named *decodeLs8Qa*. The function returns a dictionary of all conditions, where each condition contains an extracted value. Here are examples how to use extracted values in evalScript:

- evalScript = "return [decodeLs8Qa(BQA).cloud];";
- evalScript = "return [decodeLs8Qa(BQA).designatedFill];";
- evalScript = "return [decodeLs8Qa(BQA).occlusion];";
- evalScript = "return [decodeLs8Qa(BQA).radiometricSaturation * 0.33];";
- evalScript = "return [decodeLs8Qa(BQA).cloudConfidence * 0.33];";
- evalScript = "return [decodeLs8Qa(BQA).cloudShadowConfidence * 0.33];";
- evalScript = "return [decodeLs8Qa(BQA).snowIceConfidence * 0.33];";
- evalScript = "return [decodeLs8Qa(BQA).cirrusConfidence * 0.33];";

Often our users would like to get all available dates for specific area of interest (e.g. agriculture field) together with cloud coverage. The basic cloud coverage meta-data that we provide through our services is based on scene meta-data and is valid for 100km x 100km area, which is often not really useful if you are looking at one hectare field.

What we recommend to do in this case is:

1. Create a new layer configuring it to show cloud data. Make sure you output actual cloud values (e.g. 1=cloud, 0=not cloud) rather than cloud mask as an image (e.g. red=cloud, transparent=no cloud)..

2. You can use one of several cloud detection options, such as:

Or you define some of your own. For this exercise we will use L2A scene classification. The custom script would look something along the lines:

switch (SCL) {
  // No Data (Missing data)    
  case 0: return [0];
  // Saturated or defective pixel   
  case 1: return [0];
  // Cloud shadows
  case 3: return [0];
  // Cloud medium probability
  case 8: return [1];    
  // Cloud high probability 
  case 9: return [1];
  // Thin cirrus 
  case 10: return [1];
  default : return [0];

3.  Use Statistical API to query the cloud layer values over specified time range (e.g. 2017-01-01/2017-12-31) over your area of interest specified as GEOMETRY parameter.

4. Output of the service will give you array of all dates along with mean value of "cloud" for each of the dates. Mean value "0" means there are no clouds, "1" fully covered, "0.7" 70% covered.

To avoid problems of negative values in GeoTiff format, we have integrated DEM in a way that:

  • elevation above the sea level is stored as it is (e.g. 0-8.848 meters)
  • elevation bellow sea level is stored from 65535 downward (e.g. "-10 meters" is stored as 65525)

To implement your own visualization, you can write a script along the following ways, e.g. "terrain if sea level rises for 2 meters":

if (DEM >= 32768) {
  elevation = DEM - 65535.0;
else {
  elevation = DEM;
if (elevation > 2.0) {
  return [0,0,1];
else {
  return [elevation/1000,elevation/1000,elevation/1000];

Image Download and Custom Legends

You can turn off the logo in Configuration Utility - just open “Instance configuration” and uncheck “Show logo":


A legend can be added to the exported image by turning on the option “Show legend” when exporting an image.

A legend may be defined in the advanced layer editor.

Add the "legend" object in the parent “styles”. A legend is specified as JSON object that must have a property named "type" with value "continuous" or "discrete", depending on a legend type. A continuous legend also needs properties "minPosition" and "maxPosition" of a floating point type, and an array that contains stop points of a gradient. Each point must have a position of a floating point type and a color in rgb hexadecimal format. A color can also be specified using rgb function that accepts percentage values for rgb triplet, just like in CSS language. A point can optionally have a label. Here is a JSON object example of a continuous legend and the legend itself:

  "type": "continuous",
  "minPosition": 0.0,
  "maxPosition": 1.05,
  "gradients": [
    { "position": 0, "color": "rgb(0%,0%,0%)" },
    { "position": 0.05, "color": "rgb(0%,0%,0%)", "label": "- 1.0" },
    { "position": 0.050001, "color": "rgb(75%,75%,75%)" },
    { "position": 0.1, "color": "rgb(75%,75%,75%)" },
    { "position": 0.10001, "color": "rgb(86%,86%,86%)" },
    { "position": 0.15, "color": "rgb(86%,86%,86%)" },
    { "position": 0.150001, "color": "rgb(100%,100%,88%)" },
    { "position": 0.2, "color": "rgb(100%,100%,88%)", "label": "0.0" },
    { "position": 0.20001, "color": "rgb(100%,98%,80%)" },
    { "position": 0.25, "color": "rgb(100%,98%,80%)" },
    { "position": 0.250001, "color": "rgb(93%,91%,71%)" },
    { "position": 0.3, "color": "rgb(93%,91%,71%)" },
    { "position": 0.30001, "color": "rgb(87%,85%,61%)" },
    { "position": 0.35, "color": "rgb(87%,85%,61%)" },
    { "position": 0.350001, "color": "rgb(80%,78%,51%)" },
    { "position": 0.4, "color": "rgb(80%,78%,51%)" },
    { "position": 0.40001, "color": "rgb(74%,72%,42%)" },
    { "position": 0.45, "color": "rgb(74%,72%,42%)" },
    { "position": 0.450001, "color": "rgb(69%,76%,38%)" },
    { "position": 0.5, "color": "rgb(69%,76%,38%)" },
    { "position": 0.50001, "color": "rgb(64%,80%,35%)" },
    { "position": 0.55, "color": "rgb(64%,80%,35%)" },
    { "position": 0.550001, "color": "rgb(57%,75%,32%)" },
    { "position": 0.6, "color": "rgb(57%,75%,32%)", "label": "0.2" },
    { "position": 0.60001, "color": "rgb(50%,70%,28%)" },
    { "position": 0.65, "color": "rgb(50%,70%,28%)" },
    { "position": 0.650001, "color": "rgb(44%,64%,25%)" },
    { "position": 0.7, "color": "rgb(44%,64%,25%)" },
    { "position": 0.70001, "color": "rgb(38%,59%,21%)" },
    { "position": 0.75, "color": "rgb(38%,59%,21%)" },
    { "position": 0.750001, "color": "rgb(31%,54%,18%)" },
    { "position": 0.8, "color": "rgb(31%,54%,18%)" },
    { "position": 0.80001, "color": "rgb(25%,49%,14%)" },
    { "position": 0.85, "color": "rgb(25%,49%,14%)" },
    { "position": 0.850001, "color": "rgb(19%,43%,11%)" },
    { "position": 0.9, "color": "rgb(19%,43%,11%)" },
    { "position": 0.90001, "color": "rgb(13%,38%,7%)" },
    { "position": 0.95, "color": "rgb(13%,38%,7%)" },
    { "position": 0.950001, "color": "rgb(6%,33%,4%)" },
    { "position": 0.990001, "color": "rgb(6%,33%,4%)" },
    { "position": 1.0, "color": "rgb(0%,27%,0%)", "label": "0.6" },
    { "position": 1.05, "color": "rgb(0%,27%,0%)" }

A discrete legend must have an array of objects that have a color and label. Here is a JSON object example of a discrete legend and the legend itself:

         "label":"No Data (Missing data)"
         "label":"Saturated or defective pixel"
         "label":"Dark features / Shadows "
         "label":"Cloud shadows"
         "label":"Cloud medium probability"
         "label":"Cloud high probability"
         "label":"Thin cirrus"
         "label":"Snow or ice"

Legends are accessible at{instanceId}?service=WMS&request=GetLegendGraphic&layer={layer}&height={height}&width={width}, where height and/or width can be omitted.

You can add a parameter GEOMETRY as in this example:<INSTANCE_ID>?SERVICE=WMS&REQUEST=GetMap&VERSION=1.3.0&LAYERS=TRUE_COLOR&MAXCC=20&WIDTH=640&HEIGHT=640&CRS=EPSG:4326
-7.877244 38.546511,
-7.876377 38.547818,
-7.871950 38.546125,
-7.872611 38.545023,
-7.871241 38.544475,
-7.869831 38.544560,
-7.866011 38.550445,
-7.872323 38.552895,
-7.874112 38.551451,
-7.877110 38.552537,
-7.878791 38.552976,
-7.879413 38.553099,
-7.880600 38.553320,
-7.881314 38.553126,
-7.882678 38.552762,
-7.883951 38.552667,
-7.885064 38.552160,
-7.885370 38.549346,
-7.877244 38.546511))

It is recommended to simplify geometry before passing it as a parameter to avoid exceeding maximum number of characters in URL.

If one wants to have a transparent background outside of the clipped geometry, he can use "FORMAT=image/png" parameter in the call and dataMask band in the evlascript as explained here. Do note however that png images are larger in size and will therefore take longer to load.

Projections depend on the use case, however since Sentinel-2 data is originally provided in the UTM projection this is also a good choice for export. For larger areas spanning multiple UTM zones a more global projection is preferable, such as Web Mercator (EPSG:3857) or WGS84 (EPSG:4326) .

Read about the available output formats here.


The list of the available standard OGC URL parameters are available here and the advanced URL parameters are available here.

In case you would like to get point values at some location (e.g. reflectance, NDVI, etc.) you can use the GetFeatureInfo request (e.g. "Identify features" or "feature info" in various GIS applications), e.g:<INSTANCE_ID>?SERVICE=WMS&VERSION=1.3.0&REQUEST=GetFeatureInfo&I=0&J=0&QUERY_LAYERS=NDVI&INFO_FORMAT=application/json&BBOX=38.55105530425345,-7.883667078518689,38.55269383803389,-7.885252872445627&CRS=EPSG:4326&MAXCC=100&WIDTH=1&HEIGHT=1&TIME=2017-03-16

Check also Statistical API.

Use Sentinel Hub WFS request and retrieve all relevant geometries for given bounding box and time frame. From the response gather the unique dates. For each date, construct a WCS request to retrieve the image.
See the code example bellow.

    // using Sentinel Hub OGC web services -
    // config
    window.layerName = '1_NATURAL_COLOR';
    window.from = '2015-01-01'; = '2017-04-20';
    window.bbox = '-410925.4640611076,4891969.810251283,-391357.58482010243,4911537.689492286';
    window.maxFeatures = 100; // 100 is max
    let images = [];
    let url = `${window.SENTINEL_HUB_INSTANCE_ID}
    (async () => {
        // retrieving
        // relevant geometries/images in bbox at time from-to
        // Sentinel Hub - WFS request -
        try {
            let response = await fetch(url);
            let data = await response.json();
            relevantGeometries = data;
            return data;
        } catch (e) {
            throw new Error('There was an error fetching the list of geometries from WFS service.\nDid you 
                            substitute your SENTINEL_HUB_INSTANCE_ID?');
    })().then(geometries => {
        // parsing
        // relevant geometries -> all relevant dates
        if(geometries.features === undefined) geometries.features = []
        let dates = new Set();
        geometries.features.forEach(value => {
        return Array.from(dates);            
    }).then(dates => {
        // mapping
        // dates -> image url
        // images available via WCS request -
        dates.forEach(date => {
            let niceName = `${window.layerName} from ${date}.tiff`;
            niceName = encodeURIComponent(niceName);
            let imageUrl = `${window.SENTINEL_HUB_INSTANCE_ID}
    let shout = value => {
        console.log('Images', value);

When ordering PlanetScope data, users have two main options - Individual Orders and Subscriptions.

What is a Subscriptions API and how does it differ from Order by Query?

When configuring a subscription, the user subscribes to a specific area of interest (polygon), and then gets all the products for that parcel in a specified (including open) time range. This option is especially useful for those interested in an ongoing monitoring of a specific area, such as an agricultural parcel. Subscriptions is similar to Order by Query, but there are several important differences between the two:

  • using Subscriptions API, there is no limit in how many products can be ordered, while in Order by Query, the limit is 250 products.
  • subscriptions API time range can cover not only past and present dates, but also future dates. A user can thus subscribe to all the data for a specific parcel for the past 5 years, as well as for all data in the future (as long as the commercial subscription is active). Doing so, past data products will be ingested right away, and future data products will be ingested automatically as soon as available.

Subscription API pricing

There is no additional cost for use of this option. PlanetScope data are offered under Hectares under Management, which is priced per area monitored per year anyway (See this FAQ.)

How to configure a Subscription?

See documentation on PlanetScope subscriptions, and check the API reference as well. You will need a Sentinel Hub account and PlanetScope quota purchased to order a subscription. If you are conducting research or if you need commercial data for precommercial exploitation, you can get your Sentinel Hub account and PlanetScope quota sponsored by ESA’s Network of Resources.

Ordering TPDI data is easiest using our Requests Builder. See also our commercial data webinar, where you can see how to make individual orders in Requests Builder (making subscriptions orders is very similar to PlanetScope Order by Query).

  1. Set the desired time range. You can set any time range you like, including an open one. To get an open subscription, leave the "To" parameter empty (""To":""). This will extend your description indefinitely.
  2. Set your area of interest
  3. Set the maximum allowed cloud coverage and serch for data to see the available products (not including future products - in case of time-range extending into the future, new products will be added)
  4. Specify the name of your subscription
  5. Specify a target collection either manually, or by selecting from the dropdown menu. If you want to create a new collection for this purpose, select "create a new collection". For each subsequent subscription, it is recommended to ingest into an existing collection. Note that only Planet collections with compatible bands will be available to chose from; for example, if your Subscriptions order has analytic_sr_udm2 set as the Product Bundle, only your Planet collections ingested with analytic_sr_udm2 Product Bundle will be offered.
  6. Enter your Planet API key (acquired after purchasing PlanetScope TPDI quota)
  7. Place your order by clicking the Place Order button. This will not yet execute the subscription. The order status will be CREATED.
  8. Confirm your order by clicking the Start button. This will run your subscription order. Note that order and status will change to RUNNING. Note that in case your subscription extends into the future, the order will stay RUNNING until the "To" date passes and until all products are ingested. All the products that are already available will ingest right away (might take a few hours if there are many).

  • Next, check your Subscription in the Dashboard. Open the 3d Party Data tab (1) and toggle on the Subsriptions pannel (2). Here you will see all your commercial subscriptions listed.
  • Opening the Subscription will show the collection ID (green, to be used to access data), order status (blue), geometry (violet) and ingested products, their status (DELIVERED, PROCESSING, DONE or FAILED), as well as the creation date (orange).

Visualize Subscription data

Visualizing commercial subscription data is no different than visualizing commercial data ordered using the Order option. See our webinar on commercial data to learn all about commercial data, including how to visualize it.

Images are ordered by “Mosaic order” priority (see Configuration Utility, can be set for each layer; you can also set this in a parameter). You can choose either to have most recent on top or least cloud coverage. You should also take into account “maximum cloud coverage” parameter.

In case you want to get the most recent images acquired, you should set maximum cloud coverage to 100% and priority to “most recent”

OGC consortium specifications for WMS, WFS, WCS, … services define the coordinate axis order. Older OGC service specifications assumed "X, Y" order for all coordinate reference systems (CRSs), even for WGS84 (EPSG:4326), while newer OGC service specifications obey the axis orders defined by the CRS's, not assuming "X, Y" order anymore. 

Sinergise services conform to the standards definitions. The WGS84 axis order are thus version dependent:

- WMS:
   - version 1.1.1: longitude, latitude
   - version 1.3.0: latitude, longitude
- WFS:
   - version 1.0.0: longitude, latitude
   - version 2.0.0: latitude, longitude
- WCS:
   - version 1.0.0: longitude, latitude

The user should always request a specific version of OGC services by providing and explicit "VERSION" parameter in the URL.

You can use rjson R package and then convert the JSON object into an R object as in the following code snippets:

loadFisResponse <- function(fisQuery) {
    return rjson::fromJSON(paste(readLines(fis_query), colapse = ""))
getDates <- function(fisResponse) {
    numberOfDates <- length(fisResponse[[1]])
    datesVector <- rep("", numberOfDates)
    for (listIndex in 1:numberOfDates) {
        datesVector[listIndex] <- fisResponse[[1]][[listIndex]]$date
makeHistogram <- function(fisResponse, itemIndex) {
    h <- fisResponse[[1]][[itemIndex]]$histogram
    numberOfBins <- length(h$bins)
    counts = rep(0, numberOfBins)
    values = rep(0, numberOfBins)
    for (i in 1:numberOfBins) {
        counts[i] <- h$bins[[i]]$count
        values[i] <- h$bins[[i]]$value
    return(data.frame(values, counts))
getBasicStats <- function(fisResponse, itemIndex) {
    stats <- fisResponse[[1]][[itemIndex]]$basicStats
    minValue <- stats$min
    maxValue <- stats$max
    meanValue <- stats$mean
    standardDeviation <- stats$stDev
    return(data.frame(minValue, maxValue, meanValue, standardDeviation))
getNumberOfDates <- function(fisResponse) {

The fisResponse object is expected to be a nested list that reflects the output format specified under FIS documentation.

This answer is a summarized and harmonized description related to this forum thread. We will be updating the answer in line with users' feedback so that it contains a consistent set of information.

End of June we will set S2 L1C bucket as “Requester pays” similarly as it is for S2 L2A and S1 GRD. This move is required to allow further increase of the shared data - for continuation of Sentinel-2 L1C coverage, to accommodate global rollout of Sentinel-2 L2A and to host European and then global Sentinel-2 analysis ready mosaics.

How might this affect your workflow:

  1. If you are using the data within AWS EU (Frankfurt) region using S3 protocol, there will be practically no change. There will be some very small additional charge incurred to your account, related to “GET, SELECT and all other Requests”, currently at 0.43$ per 1 million requests.
  2. If you are using the data within any other AWS region using S3 protocol, there will be a small data transfer charge incurred to your account - "Data transfer OUT from Amazon EC2 To Another AWS region", currently at 0.02 USD per GB. You can avoid this by setting up part (or all) of your processing to AWS EU (Frankfurt) region.
  3. If you are using the data within AWS using HTTP protocol, you will need to sign requests (more info here). You will find examples on how to do it here. We will also upgrade our sentinelhub-py python libraries to work with S3 data soon (by mid of May latest) to make it easier for you.
  4. If you are using data outside of AWS, you should consider setting up AWS instance within EU-1 region. There is free tier available ( and you might be applicable for AWS research credits ( Alternatively see this thread on how it is possible to access data directly over Internet. Note that there will be a small charge for this as well "Data transfer OUT from Amazon EC2 To Internet", currently at 0.05-0.09 USD per GB.

Note that whichever category you fall into above, you will need to make changes to your code to continue to access Sentinel-2 data on AWS. In most cases, it’s as simple as adding a flag to your object request.

As there are several web applications out there making use of Sentinel meta-data, we have decided to make some of these data available over HTTP permanently:

  • L1C and L2A tiles
    • readme.html
    • preview.jpg
    • tileInfo.json
    • productInfo.json
    • metadata.xml
  • L1C and L2A products
    • readme.html
    • metadata.xml
    • productInfo.json

In case you believe we should make some other meta-data available in a similar manner, describe the need in the thread bellow.

We understand that this change might be an inconvenience to some users. However, the goal of this experiment is to discover how best to stage data for analysis and processing in the cloud. When the Sentinel Public Data Collection was established two years ago, getting hold of Sentinel imagery was quite a challenge. It was distributed in unwieldy chunks and Copernicus SciHub had trouble managing the demand. And there was no other place to get it. At that time, we made a decision to make the data available as easily as possible and as openly as possible. Things are changing now, with the collaborative ground segment running, four DIAS-es coming in a few months, and data generally being more easily accessible. So we believe the time is now right to go back to original purpose – experimenting with how best to stage data for analysis in the cloud.

All Sentinel Hub services are available using both HTTP and HTTPS protocols.

To prevent overloading the system and to improve user experience, we have a rate limiting system in place. Find more info about it here. In case you need higher limit, contact support.

Yes, we have implemented Google reCAPTCHA technology for our web applications to avoid revealing security credentials. The option is also available for our Enterprise users. Find out more in our API documentation.

Integrate Data into GIS and Web applications

At the moment, Sentinel Hub OGC only works in ArcGIS Online, if you have an ArcGIS Organizational account and you configure its CORS settings to allow specific domains to communicate with the server, as described in this ArcGIS Online documentation. Unless you do so, none of the imported layers will display an image.

1. Go to 
2. Sign up and login to Canvas.
3. Click on WMS Services in the left menu as shown below:

4. Click Add WMS Layer as shown below:

5. Enter the WMS Service information for Sentinal in the URL field  

6. Go to Projects, and click the Add Project Button as show below:

7. In the Project you created above, click the Maps button as shown below:

8. Click the Add Map button as shown below:

9. In the left menu of the new map, expand the WMS layer you created in step 4 above. Toggle the desired layer(s). Below, we are adding the NDVI layer.

10. Define the Geometry Area

      There are two method you can use to define a Geometry Area:

      1. A data layer
      2. Draw a Polygon or Rectange area

While there are some simple use-cases in which you might wish to draw an area, in most cases you will be using a data layer.  
Below, we are using a data layer of the state of Rhode Island.

11. Click the settings icon on the NDVI Layer you created in Step 9 above. Select ‘Geometry’ from the menu as shown below:

12. Select the Geometry Area
      a.    For a data layer (such as we are using), select Custom as the Geometry Area
      b.    For a polygon you have created via the free-hand toolbar, select Polygon

13. Click Save and then click the Save button for your map. 

14. Congratulations! Your map is now ready.

  1. Configure your Instance in Configuration Utility.
  2. Click “VIEW IN PLAYGROUND” button.
  3. Click
    button at the top right corner to open snippet tool.
  4. Select the Google Maps maps library, type your Google Maps Api key and copy the code generated for the configured visualization.

Google maps
Figure 1: Snippet tool is accessible in Sentinel Playground if it’s opened from Configuration Utility. Before integration, you must enter your Google Maps API key.

Watch our OGC webinar to learn how to integrate satellite imagery into web applications using Leaflet.

  1. Configure your Instance in Configuration Utility.
  2. Click “VIEW IN PLAYGROUND” button.
  3. Click
    button at the top right corner to open snippet tool.
  4. Select the Leaflet maps library and copy the code generated for the configured visualization.


Figure 1: Snippet tool is accessible in Sentinel Playground if it’s opened from Configuration Utility.

  1. Configure your Instance in Configuration Utility.
  2. Click “VIEW IN PLAYGROUND” button.
  3. Click
    button at the top right corner.
  4. Select the OpenLayers maps library and copy the code generated for the configured visualization.

Open layers
Figure 1: Snippet tool is accessible in Sentinel Playground if it’s opened from Configuration Utility.

In some cases ArcMap turns on all layers and calls WMS. Sentinel Hub WMS service does not support visualisation of many layers at the same time. We suggest you turn off all layers and turn them on one by one.

If you get the following error:

ArcMap error

Turn off all layers and turn them on one by one:

ArcMap error

Bring Your Own Data

To prepare data, check out our documentation here

Sentinel Hub does not keep any copies of your own data. During the process of ingestion, we will read each file once to establish the index. Index will be stored on our side until you decide to remove the data from Sentinel Hub. Whenever a request will come, we will read the relevant parts of the file, in order to provide results, keeping it in the memory. Results are streamed to the user and memory contents are discarded.

In no step of this process is any data stored as a file, not even temporarily. Once you decide to remove the data, we will delete all information we have about it.