diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index b7d5cab..9422790 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -20,11 +20,17 @@ Added
 - ``raster.Image()``: With Statement Context Manager for Image #45
 - ``raster.Image()``: Alter image array #67
 
+Fixed
+*****
+- ``data.Source()``: Fixed query metadata return for new EarthExplorer API #71
+- ``raster.Image()``: Consider all image bands in `pad()` #59
+
 Changed
 *******
 - ``data.Metadata()``: Corrected field types #58
 - ``data.MetadataCollection()``: Improved plotting of MetadataCollection to_pandas method #56
 - ``data.MetadataCollection()``: Made filter method more flexible with list and fuzzy filter options #55
+- ``raster.Image()``: Split `_pad_to_bbox()` into `pad()` and `_get_pad_width()`, updated `mask()` #59
 
 Removed
 *******
diff --git a/ukis_pysat/data.py b/ukis_pysat/data.py
index 71d054b..a21f7ff 100644
--- a/ukis_pysat/data.py
+++ b/ukis_pysat/data.py
@@ -116,7 +116,7 @@ class Source:
                 with open(meta_file) as f:
                     m = json.load(f)
                     try:
-                        self.construct_metadata(m)
+                        self.construct_metadata(meta_src=m, platform=platform)
                     except (json.decoder.JSONDecodeError, LookupError, TypeError) as e:
                         raise ValueError(f"{os.path.basename(meta_file)} not a valid metadata file. {e}.")
                     m_platform = m["properties"]["platformname"]
@@ -157,18 +157,19 @@ class Source:
             meta_src = self.api.to_geojson(meta_src)["features"]
 
         # construct MetadataCollection from list of Metadata objects
-        return MetadataCollection([self.construct_metadata(meta_src=m) for m in meta_src])
+        return MetadataCollection([self.construct_metadata(meta_src=m, platform=platform) for m in meta_src])
 
-    def construct_metadata(self, meta_src):
+    def construct_metadata(self, meta_src, platform):
         """Constructs a metadata object that is harmonized across the different satellite image sources.
 
         :param meta_src: Source metadata (GeoJSON-like mapping)
+        :param platform: Image platform (<enum 'Platform'>).
         :returns: Harmonized metadata (Metadata object)
         """
         if self.src == Datahub.File:
             meta = Metadata(
                 id=meta_src["properties"]["id"],
-                platformname=Platform(meta_src["properties"]["platformname"]),
+                platformname=platform,
                 producttype=meta_src["properties"]["producttype"],
                 orbitdirection=meta_src["properties"]["orbitdirection"],
                 orbitnumber=int(meta_src["properties"]["orbitnumber"]),
@@ -187,12 +188,7 @@ class Source:
         elif self.src == Datahub.EarthExplorer:
             meta = Metadata(
                 id=meta_src["displayId"],
-                platformname=Platform(
-                    meta_src["dataAccessUrl"][
-                        meta_src["dataAccessUrl"].find("dataset_name=")
-                        + len("dataset_name=") : meta_src["dataAccessUrl"].rfind("&ordered=")
-                    ]
-                ),
+                platformname=platform,
                 producttype="L1TP",
                 orbitdirection="DESCENDING",
                 orbitnumber=int(
@@ -203,7 +199,7 @@ class Source:
                 relativeorbitnumber=int(meta_src["summary"][meta_src["summary"].find("Row: ") + len("Row: ") :]),
                 acquisitiondate=meta_src["acquisitionDate"],
                 ingestiondate=meta_src["modifiedDate"],
-                cloudcoverpercentage=float(round(meta_src["cloudCover"], 2)) if "cloudCover" in meta_src else None,
+                cloudcoverpercentage=round(float(meta_src["cloudCover"]), 2) if "cloudCover" in meta_src else None,
                 format="GeoTIFF",
                 srcid=meta_src["displayId"],
                 srcurl=meta_src["dataAccessUrl"],
@@ -214,14 +210,14 @@ class Source:
         else:
             meta = Metadata(
                 id=meta_src["properties"]["identifier"],
-                platformname=Platform(meta_src["properties"]["platformname"]),
+                platformname=platform,
                 producttype=meta_src["properties"]["producttype"],
                 orbitdirection=meta_src["properties"]["orbitdirection"],
                 orbitnumber=int(meta_src["properties"]["orbitnumber"]),
                 relativeorbitnumber=int(meta_src["properties"]["relativeorbitnumber"]),
                 acquisitiondate=meta_src["properties"]["beginposition"],
                 ingestiondate=meta_src["properties"]["ingestiondate"],
-                cloudcoverpercentage=float(round(meta_src["properties"]["cloudcoverpercentage"], 2))
+                cloudcoverpercentage=round(float(meta_src["properties"]["cloudcoverpercentage"]), 2)
                 if "cloudcoverpercentage" in meta_src["properties"]
                 else None,
                 format=meta_src["properties"]["format"],
diff --git a/ukis_pysat/raster.py b/ukis_pysat/raster.py
index 23320de..ddaa012 100644
--- a/ukis_pysat/raster.py
+++ b/ukis_pysat/raster.py
@@ -102,20 +102,27 @@ class Image:
         valid_data_window = windows.get_data_window(self.__arr, nodata=nodata)
         return windows.bounds(valid_data_window, windows.transform(valid_data_window, self.dataset.transform))
 
-    def mask(self, bbox, crop=True, pad=False, mode="constant", constant_values=0):
-        """Mask the area outside of the input shapes with no data.
+    def mask(self, bbox, crop=True, pad=False, fill=False, mode="constant", constant_values=0):
+        """Mask raster to bbox.
 
         :param bbox: bounding box of type tuple or Shapely Polygon
         :param crop: bool, see rasterio.mask. Optional, (default: True)
-        :param pad: pads image, should only be used when bbox.bounds extent img.bounds, optional (default: False)
-        :param mode: str, how to pad, see rasterio.pad. Optional (default: 'constant')
+        :param fill: enforce raster to cover bbox. if raster extent is smaller than bbox it will be filled according to
+            mode and constant_values parameters. Optional (default: False)
+        :param mode: str, how to fill, see rasterio.pad. Optional (default: 'constant')
         :param constant_values: nodata value, padding should be filled with, optional (default: 0)
         """
-        # TODO https://github.com/mapbox/rasterio/issues/995
         if pad:
-            self.dataset.close()
-            # here we __update_dataset()
-            self.dataset = self._pad_to_bbox(bbox, mode, constant_values)
+            from warnings import warn
+            warn("`pad` was renamed to `fill` in `mask()` and will be removed with version 0.7.0", DeprecationWarning)
+            fill = pad
+
+        # TODO https://github.com/mapbox/rasterio/issues/995
+        if fill:
+            pad_width = self._get_pad_width(bbox)
+            if pad_width > 0:
+                # only pad raster if it is smaller than bbox
+                self.dataset = self.pad(pad_width, mode, constant_values)
 
         if isinstance(bbox, polygon.Polygon):
             self.__arr, transform = rasterio.mask.mask(self.dataset, [bbox], crop=crop)
@@ -129,14 +136,12 @@ class Image:
         # passing meta to open, because driver gets lost if it's not GTiff
         self.dataset = self.__update_dataset(self.dataset.crs, transform, nodata=self.dataset.nodata)
 
-    def _pad_to_bbox(self, bbox, mode="constant", constant_values=0):
-        """Buffers array with biggest difference to bbox and adjusts affine transform matrix. Can be used to fill
-        array with nodata values before masking in case bbox only partially overlaps dataset bounds.
+    def _get_pad_width(self, bbox):
+        """Calculates biggest difference from raster bounds to bbox. Can be used with pad() to fill array with
+        nodata values before masking in case bbox only partially overlaps dataset bounds.
 
-        :param bbox: bounding box of type tuple or Shapely Polygon
-        :param mode: str, how to pad, see rasterio.pad. Optional (default: 'constant')
-        :param constant_values: nodata value, padding should be filled with, optional (default: 0)
-        :return: closed, buffered dataset in memory
+        :param bbox: bounding box of type tuple or Shapely Polygon.
+        :return: pad width in pixels, int.
         """
         if isinstance(bbox, polygon.Polygon):
             bbox = bbox.bounds
@@ -149,8 +154,16 @@ class Image:
         max_diff_ll = np.max(np.subtract(tuple(self.dataset.bounds[:2]), bbox[:2]))
         max_diff = max(max_diff_ll, max_diff_ur)  # buffer in units
 
-        pad_width = math.ceil(max_diff / self.dataset.transform.to_gdal()[1])  # units / pixel_size
+        return math.ceil(max_diff / self.dataset.transform.to_gdal()[1])  # units / pixel_size
+
+    def pad(self, pad_width, mode="constant", constant_values=0):
+        """Pad raster in all directions.
 
+        :param pad_width: pad width in pixels, int.
+        :param mode: str, how to pad, see rasterio.pad. Optional (default: 'constant')
+        :param constant_values: nodata value, padding should be filled with, optional (default: 0)
+        :return: closed, buffered dataset in memory
+        """
         destination = np.zeros(
             (self.dataset.count, self.__arr.shape[1] + 2 * pad_width, self.__arr.shape[2] + 2 * pad_width,),
             self.__arr.dtype,
@@ -158,7 +171,7 @@ class Image:
 
         for i in range(0, self.dataset.count):
             destination[i], transform = rasterio.pad(
-                self.__arr[0], self.dataset.transform, pad_width, mode, constant_values=constant_values,
+                self.__arr[i], self.dataset.transform, pad_width, mode, constant_values=constant_values,
             )
 
         self.__arr = destination

Handle case where pad_width<0 in _pad_to_bbox
Currently [_pad_to_bbox](https://github.com/dlr-eoc/ukis-pysat/blob/96196d955f28b96249b9b00e56c24321963f0a79/ukis_pysat/raster.py#L112) cannot deal with cases where pad_width happens to be <0 (e.g., when bbox is smaller than image and no padding would be required). We should be able to handle such cases and not immediately throw an error. A simple way would be to set pad_width=0 in such cases. The following would be possible implementation:

```python
    def _pad_to_bbox(self, bbox, mode="constant", constant_values=0):
        """Buffers array with biggest difference to bbox and adjusts affine transform matrix. Can be used to fill
        array with nodata values before masking in case bbox only partially overlaps dataset bounds.
        :param bbox: bounding box of type tuple or Shapely Polygon
        :param mode: str, how to pad, see rasterio.pad. Optional (default: 'constant')
        :param constant_values: nodata value, padding should be filled with, optional (default: 0)
        :return: closed, buffered dataset in memory
        """
        if isinstance(bbox, polygon.Polygon):
            bbox = bbox.bounds
        elif isinstance(bbox, tuple):
            pass
        else:
            raise TypeError(f"bbox must be of type tuple or Shapely Polygon")

        max_diff_ur = np.max(np.subtract(bbox[2:], tuple(self.dataset.bounds[2:])))
        max_diff_ll = np.max(np.subtract(tuple(self.dataset.bounds[:2]), bbox[:2]))
        max_diff = max(max_diff_ll, max_diff_ur)  # buffer in units

        pad_width = math.ceil(max_diff / self.dataset.transform.to_gdal()[1])  # units / pixel_size

        if pad_width < 0:
            # make sure that pad_width is not negative
            pad_width = 0

        destination = np.zeros(
            (self.dataset.count, self.__arr.shape[1] + 2 * pad_width, self.__arr.shape[2] + 2 * pad_width,),
            self.__arr.dtype,
        )

        for i in range(0, self.dataset.count):
            destination[i], transform = rasterio.pad(
                self.__arr[i], self.dataset.transform, pad_width, mode, constant_values=constant_values,
            )

        self.__arr = destination

        self.dataset.close()
        return self.__update_dataset(self.dataset.crs, transform, nodata=self.dataset.nodata)
```
diff --git a/tests/test_raster.py b/tests/test_raster.py
index d41b9d2..0bf67ca 100644
--- a/tests/test_raster.py
+++ b/tests/test_raster.py
@@ -156,7 +156,7 @@ class DataTest(unittest.TestCase):
         )
 
         self.img.mask(
-            box(11.8919236802142620, 51.4664152338322580, 11.9477435281016131, 51.5009522690838750,), pad=True,
+            box(11.8919236802142620, 51.4664152338322580, 11.9477435281016131, 51.5009522690838750,), fill=True,
         )
         self.assertEqual(
             self.img.dataset.bounds,

pip install -e .[complete]
parse_log_pytest
requirements.txt
pytest
apt-get update apt-get install -y gcc
3.7
requirements.txt
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
affine==2.4.0
appdirs==1.4.4
attrs==24.2.0
certifi @ file:///croot/certifi_1671487769961/work/certifi
chardet==3.0.4
click==7.1.2
click-plugins==1.1.1
cligj==0.7.2
dask==2.14.0
decopatch==1.4.10
exceptiongroup==1.2.2
Fiona==1.8.22
geographiclib==2.0
geojson==3.2.0
geomet==1.1.0
geopy==2.4.1
html2text==2020.1.16
idna==2.10
importlib-metadata==6.7.0
iniconfig==2.0.0
landsatxplore==0.6
makefun==1.15.6
munch==4.0.0
numpy==1.18.5
packaging==24.0
pandas==1.0.5
Pillow==7.1.2
pluggy==1.2.0
pyfields==1.1.5
pylandsat==0.4
pyparsing==3.1.4
pyproj==2.6.1.post1
pytest==7.4.4
python-dateutil==2.8.2
pytz==2025.2
rasterio==1.1.8
requests==2.23.0
rio-mucho==1.0.0
rio-toa==0.3.0
sentinelsat==0.14
Shapely==1.7.1
six==1.17.0
snuggs==1.4.7
tomli==2.0.1
toolz==0.12.1
tqdm==4.67.1
typing_extensions==4.7.1
-e git+https://github.com/dlr-eoc/ukis-pysat.git@f9d327836e9d8edef54b05866fdca02addbee52c#egg=ukis_pysat
urllib3==1.25.11
utm==0.5.0
valid8==5.1.2
zipp==3.15.0

name: ukis-pysat
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - certifi=2022.12.7=py37h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.4.4=h6a678d5_1
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=1.1.1w=h7f8727e_0
  - pip=22.3.1=py37h06a4308_0
  - python=3.7.16=h7a1cb2a_0
  - readline=8.2=h5eee18b_0
  - setuptools=65.6.3=py37h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - wheel=0.38.4=py37h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - affine==2.4.0
      - appdirs==1.4.4
      - attrs==24.2.0
      - chardet==3.0.4
      - click==7.1.2
      - click-plugins==1.1.1
      - cligj==0.7.2
      - dask==2.14.0
      - decopatch==1.4.10
      - exceptiongroup==1.2.2
      - fiona==1.8.22
      - geographiclib==2.0
      - geojson==3.2.0
      - geomet==1.1.0
      - geopy==2.4.1
      - html2text==2020.1.16
      - idna==2.10
      - importlib-metadata==6.7.0
      - iniconfig==2.0.0
      - landsatxplore==0.6
      - makefun==1.15.6
      - munch==4.0.0
      - numpy==1.18.5
      - packaging==24.0
      - pandas==1.0.5
      - pillow==7.1.2
      - pluggy==1.2.0
      - pyfields==1.1.5
      - pylandsat==0.4
      - pyparsing==3.1.4
      - pyproj==2.6.1.post1
      - pytest==7.4.4
      - python-dateutil==2.8.2
      - pytz==2025.2
      - rasterio==1.1.8
      - requests==2.23.0
      - rio-mucho==1.0.0
      - rio-toa==0.3.0
      - sentinelsat==0.14
      - shapely==1.7.1
      - six==1.17.0
      - snuggs==1.4.7
      - tomli==2.0.1
      - toolz==0.12.1
      - tqdm==4.67.1
      - typing-extensions==4.7.1
      - urllib3==1.25.11
      - utm==0.5.0
      - valid8==5.1.2
      - zipp==3.15.0
prefix: /opt/conda/envs/ukis-pysat

tests/test_raster.py::DataTest::test_mask_image
tests/test_raster.py::DataTest::test__lookup_bands tests/test_raster.py::DataTest::test_arr tests/test_raster.py::DataTest::test_context tests/test_raster.py::DataTest::test_dimorder_error tests/test_raster.py::DataTest::test_dn2toa tests/test_raster.py::DataTest::test_get_dask_array tests/test_raster.py::DataTest::test_get_subset tests/test_raster.py::DataTest::test_get_tiles tests/test_raster.py::DataTest::test_get_valid_data_bbox tests/test_raster.py::DataTest::test_init tests/test_raster.py::DataTest::test_init_fail_invalid_dataset tests/test_raster.py::DataTest::test_init_fail_invalid_path tests/test_raster.py::DataTest::test_init_with_array tests/test_raster.py::DataTest::test_init_with_arry_fail_missing_crs tests/test_raster.py::DataTest::test_init_with_arry_fail_missing_crs_and_transform tests/test_raster.py::DataTest::test_init_with_arry_fail_missing_transform tests/test_raster.py::DataTest::test_set_array tests/test_raster.py::DataTest::test_set_array_error tests/test_raster.py::DataTest::test_warp tests/test_raster.py::DataTest::test_write_to_file
CHANGELOG.rst ukis_pysat/raster.py ukis_pysat/data.py
CHANGELOG.rst ukis_pysat/raster.py ukis_pysat/data.py