Home / Notebooks / Geospatial & Remote Sensing
Geospatial & Remote Sensing
intermediate

Sentinel Hub Essentials

Complete guide to accessing and processing satellite imagery with Sentinel Hub

April 20, 2026
•
Updated regularly

Sentinel Hub Essentials

Complete guide to accessing and processing satellite imagery using Sentinel Hub APIs.

What is Sentinel Hub?

Sentinel Hub is a cloud-based platform that provides access to satellite imagery from various Earth observation missions, primarily Copernicus Sentinel satellites.

Key Features:

  • Access to Sentinel-1, Sentinel-2, Sentinel-3, Landsat, and more
  • On-the-fly image processing and analysis
  • RESTful APIs for easy integration
  • Pre-built processing scripts
  • Cloud-optimized data access (no downloads required)
  • Custom band combinations and indices (NDVI, NDWI, etc.)
  • Common Use Cases:

  • Agriculture monitoring
  • Environmental analysis
  • Urban planning
  • Disaster response
  • Change detection
  • Land cover classification
  • Prerequisites

    Requirements

  • Python 3.8 or higher
  • Sentinel Hub account (free trial available)
  • Basic understanding of satellite imagery concepts
  • Get API Credentials

    Step 1: Create Account

  • Go to https://www.sentinel-hub.com/
  • Sign up for a free trial account
  • Verify your email
  • Step 2: Get Credentials

  • Log in to Sentinel Hub Dashboard
  • Go to "User Settings" → "OAuth clients"
  • Create new OAuth client
  • Copy your CLIENT_ID and CLIENT_SECRET
  • Installation

    Install Sentinel Hub Python Package

    # Step 1: Create virtual environment (recommended)
    python -m venv venv
    source venv/bin/activate  # On Windows: venv\Scripts\activate
    
    # Step 2: Install sentinelhub package
    pip install sentinelhub
    
    # Step 3: Install additional dependencies
    pip install numpy matplotlib rasterio
    
    Verify Installation:
    python -c "import sentinelhub; print(sentinelhub.__version__)"
    

    Configuration

    Setup Authentication

    Create .env file:

    # Sentinel Hub credentials
    SH_CLIENT_ID=your_client_id_here
    SH_CLIENT_SECRET=your_client_secret_here
    SH_INSTANCE_ID=your_instance_id_here
    

    Configure in Python:

    # ========== Option 1: Using Config ==========
    from sentinelhub import SHConfig
    
    # Create configuration
    config = SHConfig()
    config.sh_client_id = 'your_client_id'
    config.sh_client_secret = 'your_client_secret'
    
    # Save configuration (persists for future use)
    config.save()
    
    # ========== Option 2: From Environment Variables ==========
    import os
    from dotenv import load_dotenv
    
    load_dotenv()
    
    config = SHConfig()
    config.sh_client_id = os.getenv('SH_CLIENT_ID')
    config.sh_client_secret = os.getenv('SH_CLIENT_SECRET')
    
    # ========== Verify Configuration ==========
    print(f"Client ID: {config.sh_client_id[:8]}...")
    print(f"Base URL: {config.sh_base_url}")
    

    Basic Concepts

    Understanding Sentinel Satellites

    Sentinel-2:

  • Optical imagery (visible and near-infrared)
  • 13 spectral bands
  • 10m to 60m resolution
  • 5-day revisit time
  • Best for: vegetation, land use, agriculture
  • Sentinel-1:

  • Synthetic Aperture Radar (SAR)
  • All-weather, day/night imaging
  • 10m resolution
  • 6-day revisit time
  • Best for: flood mapping, ship detection, ice monitoring
  • Common Spectral Bands

    # Sentinel-2 bands
    BANDS = {
        'B01': 'Coastal aerosol (443 nm)',
        'B02': 'Blue (490 nm) - 10m',
        'B03': 'Green (560 nm) - 10m',
        'B04': 'Red (665 nm) - 10m',
        'B05': 'Red Edge 1 (705 nm)',
        'B06': 'Red Edge 2 (740 nm)',
        'B07': 'Red Edge 3 (783 nm)',
        'B08': 'NIR (842 nm) - 10m',
        'B8A': 'Narrow NIR (865 nm)',
        'B09': 'Water vapour (945 nm)',
        'B10': 'SWIR Cirrus (1375 nm)',
        'B11': 'SWIR 1 (1610 nm)',
        'B12': 'SWIR 2 (2190 nm)'
    }
    

    Searching for Data

    Find Available Images

    from sentinelhub import SHConfig, DataCollection, SentinelHubCatalog
    from datetime import datetime, timedelta
    
    # ========== Setup ==========
    config = SHConfig()
    catalog = SentinelHubCatalog(config=config)
    
    # ========== Define Search Parameters ==========
    # Area of interest (bounding box)
    bbox = [13.822, 45.85, 13.835, 45.86]  # Venice, Italy [lon_min, lat_min, lon_max, lat_max]
    
    # Time range
    time_interval = (
        datetime(2024, 6, 1),
        datetime(2024, 8, 31)
    )
    
    # ========== Search for Sentinel-2 Images ==========
    search_iterator = catalog.search(
        DataCollection.SENTINEL2_L2A,  # Sentinel-2 Level-2A (atmospherically corrected)
        bbox=bbox,
        time=time_interval,
        filter="eo:cloud_cover < 20",  # Max 20% cloud cover
        fields={
            "include": ["id", "properties.datetime", "properties.eo:cloud_cover"],
            "exclude": []
        }
    )
    
    # ========== Display Results ==========
    results = list(search_iterator)
    print(f"Found {len(results)} images")
    
    for item in results[:5]:  # Show first 5
        print(f"ID: {item['id']}")
        print(f"Date: {item['properties']['datetime']}")
        print(f"Cloud Cover: {item['properties']['eo:cloud_cover']}%")
        print("-" * 50)
    
    Expected Output:
    Found 12 images
    ID: S2A_MSIL2A_20240815T100031_N0510_R122_T33TVG_20240815T171645
    Date: 2024-08-15T10:15:42Z
    Cloud Cover: 5.2%
    --------------------------------------------------
    

    Requesting Imagery

    True Color Image

    from sentinelhub import (
        SHConfig, SentinelHubRequest, DataCollection,
        BBox, CRS, MimeType, bbox_to_dimensions
    )
    
    # ========== Configuration ==========
    config = SHConfig()
    
    # ========== Define Area of Interest ==========
    bbox = BBox(bbox=[13.822, 45.85, 13.835, 45.86], crs=CRS.WGS84)
    resolution = 10  # 10 meters per pixel
    size = bbox_to_dimensions(bbox, resolution=resolution)
    
    print(f"Image size: {size} pixels")
    
    # ========== Evalscript for True Color ==========
    evalscript_true_color = """
    //VERSION=3
    
    function setup() {
        return {
            input: [{
                bands: ["B04", "B03", "B02"]  // Red, Green, Blue
            }],
            output: {
                bands: 3,
                sampleType: "AUTO"
            }
        };
    }
    
    function evaluatePixel(sample) {
        // Apply gain for brightness
        return [2.5 * sample.B04, 2.5 * sample.B03, 2.5 * sample.B02];
    }
    """
    
    # ========== Create Request ==========
    request = SentinelHubRequest(
        evalscript=evalscript_true_color,
        input_data=[
            SentinelHubRequest.input_data(
                data_collection=DataCollection.SENTINEL2_L2A,
                time_interval=('2024-08-01', '2024-08-31'),
                maxcc=0.2  # Maximum 20% cloud coverage
            )
        ],
        responses=[
            SentinelHubRequest.output_response('default', MimeType.PNG)
        ],
        bbox=bbox,
        size=size,
        config=config
    )
    
    # ========== Get Image ==========
    true_color_image = request.get_data()[0]
    
    print(f"Image shape: {true_color_image.shape}")
    print(f"Data type: {true_color_image.dtype}")
    

    Visualize with Matplotlib

    import matplotlib.pyplot as plt
    
    # ========== Display Image ==========
    plt.figure(figsize=(12, 8))
    plt.imshow(true_color_image)
    plt.title('Sentinel-2 True Color Image')
    plt.axis('off')
    plt.tight_layout()
    plt.savefig('true_color.png', dpi=300, bbox_inches='tight')
    plt.show()
    
    print("Image saved as 'true_color.png'")
    

    Vegetation Indices

    NDVI (Normalized Difference Vegetation Index)

    # ========== NDVI Evalscript ==========
    evalscript_ndvi = """
    //VERSION=3
    
    function setup() {
        return {
            input: [{
                bands: ["B04", "B08"]  // Red and NIR
            }],
            output: {
                bands: 1,
                sampleType: "FLOAT32"
            }
        };
    }
    
    function evaluatePixel(sample) {
        // NDVI = (NIR - Red) / (NIR + Red)
        let ndvi = (sample.B08 - sample.B04) / (sample.B08 + sample.B04);
        return [ndvi];
    }
    """
    
    # ========== Request NDVI ==========
    request_ndvi = SentinelHubRequest(
        evalscript=evalscript_ndvi,
        input_data=[
            SentinelHubRequest.input_data(
                data_collection=DataCollection.SENTINEL2_L2A,
                time_interval=('2024-08-01', '2024-08-31'),
                maxcc=0.2
            )
        ],
        responses=[
            SentinelHubRequest.output_response('default', MimeType.TIFF)
        ],
        bbox=bbox,
        size=size,
        config=config
    )
    
    # ========== Get NDVI Data ==========
    ndvi_data = request_ndvi.get_data()[0]
    
    # ========== Visualize NDVI ==========
    plt.figure(figsize=(12, 8))
    plt.imshow(ndvi_data, cmap='RdYlGn', vmin=-1, vmax=1)
    plt.colorbar(label='NDVI Value')
    plt.title('NDVI - Vegetation Health')
    plt.axis('off')
    plt.tight_layout()
    plt.savefig('ndvi.png', dpi=300, bbox_inches='tight')
    plt.show()
    
    # ========== Interpret NDVI Values ==========
    print("NDVI Interpretation:")
    print("  -1.0 to 0.0: Water, snow, clouds")
    print("   0.0 to 0.2: Barren rock, sand, urban areas")
    print("   0.2 to 0.4: Shrubs and grassland")
    print("   0.4 to 0.6: Moderate vegetation")
    print("   0.6 to 1.0: Dense, healthy vegetation")
    

    NDWI (Normalized Difference Water Index)

    # ========== NDWI Evalscript ==========
    evalscript_ndwi = """
    //VERSION=3
    
    function setup() {
        return {
            input: [{
                bands: ["B03", "B08"]  // Green and NIR
            }],
            output: {
                bands: 1,
                sampleType: "FLOAT32"
            }
        };
    }
    
    function evaluatePixel(sample) {
        // NDWI = (Green - NIR) / (Green + NIR)
        let ndwi = (sample.B03 - sample.B08) / (sample.B03 + sample.B08);
        return [ndwi];
    }
    """
    
    # ========== Request NDWI ==========
    request_ndwi = SentinelHubRequest(
        evalscript=evalscript_ndwi,
        input_data=[
            SentinelHubRequest.input_data(
                data_collection=DataCollection.SENTINEL2_L2A,
                time_interval=('2024-08-01', '2024-08-31'),
                maxcc=0.2
            )
        ],
        responses=[
            SentinelHubRequest.output_response('default', MimeType.TIFF)
        ],
        bbox=bbox,
        size=size,
        config=config
    )
    
    # ========== Get and Visualize ==========
    ndwi_data = request_ndwi.get_data()[0]
    
    plt.figure(figsize=(12, 8))
    plt.imshow(ndwi_data, cmap='Blues', vmin=-1, vmax=1)
    plt.colorbar(label='NDWI Value')
    plt.title('NDWI - Water Content')
    plt.axis('off')
    plt.tight_layout()
    plt.savefig('ndwi.png', dpi=300, bbox_inches='tight')
    plt.show()
    

    Time Series Analysis

    Multi-Temporal Comparison

    from sentinelhub import SentinelHubRequest, DataCollection, MimeType
    import numpy as np
    
    # ========== Define Time Periods ==========
    time_periods = [
        ('2024-01-01', '2024-01-31', 'January'),
        ('2024-04-01', '2024-04-30', 'April'),
        ('2024-07-01', '2024-07-31', 'July'),
        ('2024-10-01', '2024-10-31', 'October')
    ]
    
    # ========== Collect Images for Each Period ==========
    ndvi_series = []
    
    for start, end, label in time_periods:
        request = SentinelHubRequest(
            evalscript=evalscript_ndvi,
            input_data=[
                SentinelHubRequest.input_data(
                    data_collection=DataCollection.SENTINEL2_L2A,
                    time_interval=(start, end),
                    maxcc=0.3
                )
            ],
            responses=[
                SentinelHubRequest.output_response('default', MimeType.TIFF)
            ],
            bbox=bbox,
            size=size,
            config=config
        )
        
        ndvi = request.get_data()[0]
        ndvi_series.append((ndvi, label))
        print(f"{label}: Mean NDVI = {np.nanmean(ndvi):.3f}")
    
    # ========== Visualize Time Series ==========
    fig, axes = plt.subplots(2, 2, figsize=(16, 12))
    
    for idx, (ndvi, label) in enumerate(ndvi_series):
        ax = axes[idx // 2, idx % 2]
        im = ax.imshow(ndvi, cmap='RdYlGn', vmin=-1, vmax=1)
        ax.set_title(f'NDVI - {label}')
        ax.axis('off')
    
    plt.colorbar(im, ax=axes.ravel().tolist(), label='NDVI')
    plt.tight_layout()
    plt.savefig('ndvi_time_series.png', dpi=300, bbox_inches='tight')
    plt.show()
    

    Advanced Processing

    Cloud Masking

    # ========== Evalscript with Cloud Mask ==========
    evalscript_cloud_mask = """
    //VERSION=3
    
    function setup() {
        return {
            input: [{
                bands: ["B04", "B03", "B02", "CLM"]  // RGB + Cloud Mask
            }],
            output: {
                bands: 3,
                sampleType: "AUTO"
            }
        };
    }
    
    function evaluatePixel(sample) {
        // If cloud detected (CLM = 1), return gray
        if (sample.CLM == 1) {
            return [0.5, 0.5, 0.5];
        }
        
        // Otherwise return true color
        return [2.5 * sample.B04, 2.5 * sample.B03, 2.5 * sample.B02];
    }
    """
    
    # ========== Request with Cloud Masking ==========
    request_masked = SentinelHubRequest(
        evalscript=evalscript_cloud_mask,
        input_data=[
            SentinelHubRequest.input_data(
                data_collection=DataCollection.SENTINEL2_L2A,
                time_interval=('2024-08-01', '2024-08-31')
            )
        ],
        responses=[
            SentinelHubRequest.output_response('default', MimeType.PNG)
        ],
        bbox=bbox,
        size=size,
        config=config
    )
    
    masked_image = request_masked.get_data()[0]
    

    False Color Composite

    # ========== False Color (NIR, Red, Green) ==========
    evalscript_false_color = """
    //VERSION=3
    
    function setup() {
        return {
            input: [{
                bands: ["B08", "B04", "B03"]  // NIR, Red, Green
            }],
            output: {
                bands: 3,
                sampleType: "AUTO"
            }
        };
    }
    
    function evaluatePixel(sample) {
        // Vegetation appears red in false color
        return [2.5 * sample.B08, 2.5 * sample.B04, 2.5 * sample.B03];
    }
    """
    
    # ========== Request False Color ==========
    request_false = SentinelHubRequest(
        evalscript=evalscript_false_color,
        input_data=[
            SentinelHubRequest.input_data(
                data_collection=DataCollection.SENTINEL2_L2A,
                time_interval=('2024-08-01', '2024-08-31'),
                maxcc=0.2
            )
        ],
        responses=[
            SentinelHubRequest.output_response('default', MimeType.PNG)
        ],
        bbox=bbox,
        size=size,
        config=config
    )
    
    false_color = request_false.get_data()[0]
    
    # ========== Display ==========
    fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(16, 8))
    
    ax1.imshow(true_color_image)
    ax1.set_title('True Color')
    ax1.axis('off')
    
    ax2.imshow(false_color)
    ax2.set_title('False Color (Vegetation in Red)')
    ax2.axis('off')
    
    plt.tight_layout()
    plt.savefig('color_comparison.png', dpi=300, bbox_inches='tight')
    plt.show()
    

    Batch Processing

    Process Multiple Locations

    from sentinelhub import BBox, CRS
    
    # ========== Define Multiple Areas ==========
    locations = {
        'Venice': BBox([13.822, 45.85, 13.835, 45.86], crs=CRS.WGS84),
        'Rome': BBox([12.48, 41.88, 12.50, 41.90], crs=CRS.WGS84),
        'Milan': BBox([9.18, 45.46, 9.20, 45.48], crs=CRS.WGS84)
    }
    
    # ========== Process Each Location ==========
    results = {}
    
    for name, bbox in locations.items():
        print(f"Processing {name}...")
        
        size = bbox_to_dimensions(bbox, resolution=10)
        
        request = SentinelHubRequest(
            evalscript=evalscript_ndvi,
            input_data=[
                SentinelHubRequest.input_data(
                    data_collection=DataCollection.SENTINEL2_L2A,
                    time_interval=('2024-08-01', '2024-08-31'),
                    maxcc=0.2
                )
            ],
            responses=[
                SentinelHubRequest.output_response('default', MimeType.TIFF)
            ],
            bbox=bbox,
            size=size,
            config=config
        )
        
        ndvi = request.get_data()[0]
        results[name] = {
            'ndvi': ndvi,
            'mean': np.nanmean(ndvi),
            'std': np.nanstd(ndvi)
        }
        
        print(f"  Mean NDVI: {results[name]['mean']:.3f}")
        print(f"  Std Dev: {results[name]['std']:.3f}")
    
    # ========== Compare Results ==========
    fig, axes = plt.subplots(1, 3, figsize=(18, 6))
    
    for idx, (name, data) in enumerate(results.items()):
        axes[idx].imshow(data['ndvi'], cmap='RdYlGn', vmin=-1, vmax=1)
        axes[idx].set_title(f"{name}\nMean NDVI: {data['mean']:.3f}")
        axes[idx].axis('off')
    
    plt.colorbar(plt.cm.ScalarMappable(cmap='RdYlGn', norm=plt.Normalize(-1, 1)),
                 ax=axes, label='NDVI')
    plt.tight_layout()
    plt.savefig('batch_comparison.png', dpi=300, bbox_inches='tight')
    plt.show()
    

    Export to GeoTIFF

    Save with Geospatial Metadata

    import rasterio
    from rasterio.transform import from_bounds
    
    # ========== Get Image Data ==========
    ndvi_data = request_ndvi.get_data()[0]
    
    # ========== Define Spatial Reference ==========
    bounds = bbox.geometry.bounds  # (min_lon, min_lat, max_lon, max_lat)
    height, width = ndvi_data.shape
    
    transform = from_bounds(
        bounds[0], bounds[1], bounds[2], bounds[3],
        width, height
    )
    
    # ========== Write GeoTIFF ==========
    with rasterio.open(
        'ndvi_output.tif',
        'w',
        driver='GTiff',
        height=height,
        width=width,
        count=1,  # Number of bands
        dtype=ndvi_data.dtype,
        crs='EPSG:4326',  # WGS84
        transform=transform,
        compress='lzw'  # Compression
    ) as dst:
        dst.write(ndvi_data, 1)
        
        # Add metadata
        dst.update_tags(
            DESCRIPTION='NDVI from Sentinel-2',
            DATE='2024-08-15',
            SOURCE='Sentinel Hub'
        )
    
    print("GeoTIFF saved successfully")
    print(f"File: ndvi_output.tif")
    print(f"CRS: EPSG:4326")
    print(f"Bounds: {bounds}")
    

    Common Use Cases

    Agriculture Monitoring

    # ========== Monitor Crop Health ==========
    def analyze_crop_health(bbox, time_interval, threshold=0.6):
        """
        Analyze crop health using NDVI
        
        Args:
            bbox: Area of interest
            time_interval: Date range
            threshold: NDVI threshold for healthy vegetation
        """
        request = SentinelHubRequest(
            evalscript=evalscript_ndvi,
            input_data=[
                SentinelHubRequest.input_data(
                    data_collection=DataCollection.SENTINEL2_L2A,
                    time_interval=time_interval,
                    maxcc=0.2
                )
            ],
            responses=[
                SentinelHubRequest.output_response('default', MimeType.TIFF)
            ],
            bbox=bbox,
            size=bbox_to_dimensions(bbox, resolution=10),
            config=config
        )
        
        ndvi = request.get_data()[0]
        
        # Calculate statistics
        healthy = np.sum(ndvi > threshold)
        stressed = np.sum((ndvi > 0.2) & (ndvi <= threshold))
        total_vegetation = healthy + stressed
        
        print(f"Crop Health Analysis:")
        print(f"  Healthy vegetation: {healthy / total_vegetation * 100:.1f}%")
        print(f"  Stressed vegetation: {stressed / total_vegetation * 100:.1f}%")
        
        return ndvi
    
    # Usage
    farm_bbox = BBox([13.822, 45.85, 13.835, 45.86], crs=CRS.WGS84)
    crop_ndvi = analyze_crop_health(farm_bbox, ('2024-07-01', '2024-07-31'))
    

    Water Body Detection

    # ========== Detect Water Bodies ==========
    def detect_water(bbox, time_interval):
        """Detect water bodies using NDWI"""
        request = SentinelHubRequest(
            evalscript=evalscript_ndwi,
            input_data=[
                SentinelHubRequest.input_data(
                    data_collection=DataCollection.SENTINEL2_L2A,
                    time_interval=time_interval,
                    maxcc=0.2
                )
            ],
            responses=[
                SentinelHubRequest.output_response('default', MimeType.TIFF)
            ],
            bbox=bbox,
            size=bbox_to_dimensions(bbox, resolution=10),
            config=config
        )
        
        ndwi = request.get_data()[0]
        
        # Water typically has NDWI > 0.3
        water_mask = ndwi > 0.3
        water_pixels = np.sum(water_mask)
        total_pixels = ndwi.size
        
        print(f"Water Detection:")
        print(f"  Water coverage: {water_pixels / total_pixels * 100:.2f}%")
        print(f"  Water pixels: {water_pixels:,}")
        
        return water_mask
    
    # Usage
    water_mask = detect_water(bbox, ('2024-08-01', '2024-08-31'))
    

    Best Practices

    Optimize API Usage

    1. Use Appropriate Resolution
    # High resolution (10m) - small areas only
    size_10m = bbox_to_dimensions(bbox, resolution=10)
    
    # Medium resolution (20m) - balanced
    size_20m = bbox_to_dimensions(bbox, resolution=20)
    
    # Low resolution (60m) - large areas
    size_60m = bbox_to_dimensions(bbox, resolution=60)
    
    2. Filter by Cloud Coverage
    # Only get images with <10% clouds
    input_data = SentinelHubRequest.input_data(
        data_collection=DataCollection.SENTINEL2_L2A,
        time_interval=('2024-08-01', '2024-08-31'),
        maxcc=0.1  # 10% maximum cloud coverage
    )
    
    3. Cache Results
    import pickle
    
    # Save processed data
    with open('ndvi_cache.pkl', 'wb') as f:
        pickle.dump(ndvi_data, f)
    
    # Load cached data
    with open('ndvi_cache.pkl', 'rb') as f:
        ndvi_data = pickle.load(f)
    
    4. Batch Requests
    # Request multiple time periods in one call
    from sentinelhub import DownloadRequest
    
    requests = [
        request1.download_list[0],
        request2.download_list[0],
        request3.download_list[0]
    ]
    
    # Download all at once
    data = SentinelHubDownloadClient(config=config).download(requests)
    

    Troubleshooting

    Common Issues

    Authentication Error:
    # Verify credentials
    config = SHConfig()
    print(f"Client ID set: {bool(config.sh_client_id)}")
    print(f"Client Secret set: {bool(config.sh_client_secret)}")
    
    # Test authentication
    from sentinelhub import SentinelHubRequest
    try:
        # Simple test request
        test_request = SentinelHubRequest(...)
        print("Authentication successful!")
    except Exception as e:
        print(f"Authentication failed: {e}")
    
    No Data Found:
    # Check if images exist for your parameters
    results = list(catalog.search(
        DataCollection.SENTINEL2_L2A,
        bbox=bbox,
        time=time_interval
    ))
    
    if len(results) == 0:
        print("No images found. Try:")
        print("  - Expanding time range")
        print("  - Increasing cloud coverage threshold")
        print("  - Verifying bbox coordinates")
    
    Rate Limiting:
    import time
    
    # Add delay between requests
    for location in locations:
        process_location(location)
        time.sleep(1)  # Wait 1 second between requests
    

    Resources

  • Official Docs: https://docs.sentinel-hub.com/
  • Sentinel Hub: https://www.sentinel-hub.com/
  • Python Package: https://sentinelhub-py.readthedocs.io/
  • Custom Scripts: https://custom-scripts.sentinel-hub.com/
  • EO Browser: https://apps.sentinel-hub.com/eo-browser/
  • Copernicus Open Access Hub: https://scihub.copernicus.eu/
  • Quick Reference Card

    # ========== Setup ==========
    from sentinelhub import SHConfig, SentinelHubRequest, DataCollection
    config = SHConfig()
    config.sh_client_id = 'your_id'
    config.sh_client_secret = 'your_secret'
    
    # ========== Define Area ==========
    bbox = BBox([lon_min, lat_min, lon_max, lat_max], crs=CRS.WGS84)
    size = bbox_to_dimensions(bbox, resolution=10)
    
    # ========== Request Data ==========
    request = SentinelHubRequest(
        evalscript=your_script,
        input_data=[...],
        responses=[...],
        bbox=bbox,
        size=size,
        config=config
    )
    data = request.get_data()[0]
    
    # ========== Common Indices ==========
    # NDVI = (NIR - Red) / (NIR + Red)
    # NDWI = (Green - NIR) / (Green + NIR)
    # EVI = 2.5 * (NIR - Red) / (NIR + 6*Red - 7.5*Blue + 1)
    

    Next Steps

  • Explore custom evalscripts at https://custom-scripts.sentinel-hub.com/
  • Try different satellite data sources (Landsat, Sentinel-1)
  • Integrate with machine learning for classification
  • Build time-series analysis pipelines
  • Create automated monitoring systems
  • ---

    Last Updated: 2026-04-20 Sentinel Hub API: v3 Difficulty: Intermediate

    Topics

    Sentinel HubSatellite ImageryRemote SensingPythonGIS

    Found This Helpful?

    If you have questions or suggestions for improving these notes, I'd love to hear from you.