How to solve "s2cloudless is not defined" in an evalscript for cloud detection

“I would like to implement a function in an evalscript for cloud detection using the s2cloudless algorithm at a resolution of 10 m. I need this function to remove clouds in a collection of images in a temporal series so that I can create a cloud-free composite for B8A band. I have written the following code in a Python Script:”


// Define parameters for the s2cloudless algorithm
var cloudDetectionThreshold = 0.4;

// Setup function
function setup() {
// Specify the input bands (in this case, only band B8A)
return {
input: [“B8A”],
output: {
bands: 1

// evaluatePixel function
function evaluatePixel(sample) {
// Extract the value of band B8A
var B8A = sample.B8A;

// Calculate the cloud mask
var mask = s2cloudless.getCloudMask({ threshold: cloudDetectionThreshold });

// Apply the cloud mask to band B8A
var maskedB8A = B8A.mask(mask.not());

// Return the value of band B8A with clouds masked
return [maskedB8A];

When I run the code, I get the following error: “s2cloudless is not defined”.

In the beginning of my Python script, I inserted the following line of code
import s2cloudless
from s2cloudless import S2PixelCloudDetector
The s2cloudless module was installed by:
pip3 install s2cloudless

“Can anyone suggest how to solve the problem?”

Hi Anna,

The problem you are encountering is that S2cloudless is a Python library. In contrast, evalscripts are Javascript and so you cannot import a Python library into a piece of Javascript. I would recommend running through this example Jupyter Notebook to understand the functionalities of the S2cloudless library.

Hello William,
thanks for the reply. My goal is to create an evalscript (in JavaScript) that generates a composite of a Sentinel 2 band (for example, band B8A) with the most recent valid (cloud-free) pixels. Therefore, I would like to perform cloud detection in the evalscript using the s2cloudless algorithm with a 10m resolution. Is there a way to do this in the evalscript (using JavaScript)?

Dear @gabogef161

The simplest way to proceed forward is to use the CLM/CLP info already available in the L1C/L2A collection. These are the pre-computed cloud masks and probabilities which are available in the evalscript. However, these cloud info is computed at a lower resolution of 160m.

Is it necessary that you compute the cloud info at 10 m? If yes, then you cannot do this simply with an evalscript. This would require you to use the tree-format of the s2cloudless model and apply it in the evalscript. This is not an easy task, but I can help you on if this is what you’re interested it. Usually people who are interested in this resolve to calculating the cloud info in python.

If the pre-computed CLM and CLP are OK, then you can simply just call them in an evalscript like this:

function setup() {
  return {
    input: ["B02", "B03", "B04", "CLM", "CLP", "dataMask"],
    output: { bands: 3 },
    mosaicking: "ORBIT"

function evaluatePixel(samples) {
  let f = 2.5
  for (var i = 0; i < samples.length; i++) {
    let sample = samples[i];
    if (sample.CLM == 0 && sample.CLP/255 < 0.4) {
      return [f*sample.B04, f*sample.B03, f*sample.B02, sample.dataMask];
  return [1,0,0,1];

The script above works on a larger time span and evaluates the CLM/CLP for each orbit, then takes the image of the first orbit where the cloudless condition is fulfilled. Otherwise if no such scene is found, the red color is shown.

Let me know if there is anything else you wish to know!


Hello @matic.lubej,

Thank you very much for the comprehensive response. However, I’m interested in generating the cloud mask at a 10m resolution, even though this would result in higher computational costs.

Since I would like to perform the entire processing on Sentinel Hub and download only the final cloud-free composite (at 10m resolution), I thought about including everything in the evalscript. In fact, I don’t mind whether I use Python or JavaScript; the important thing is NOT to download individual images from my collection locally but only the final composite. Do you have any further suggestions for implementing this procedure?

Thank you.



I don’t mind whether I use Python or JavaScript; the important thing is NOT to download individual images from my collection locally but only the final composite.

Unfortunately, this requirement limits our solution to the server side, meaning that everything has to be managed in the evalscript, before actually downloading the data. However, the s2cloudless script has to be converted to javascript code, and even if it would be done, the model is too heavy and would take too long to process for this to make sense.

For heavier computations we recommend using eo-learn and eo-grow, for building EO-related process chains, with the second library having a focus on scaling.

May I ask why you would prefer downloading the final composite and avoid downloading multiple scenes and creating the mosaic yourself locally? It seems that the task you describe here is unfortunately more suited for the latter.

In our experience, we tend to be satisfied with the 160m CLM and CLP when we want to download a finalized composite. If this is not satisfactory, we download separate scenes for an area and do the processing in python offline.

Hope this helps and that the description was clear. I believe it might be necessary to re-asses what you wish to achieve and the way to approach it.


Thank you for the answer which clarified in a comprehensive manner how I can implement my procedure. I will try to implement composite locally after downloading the bands.



1 Like