[{"data":1,"prerenderedAt":2194},["ShallowReactive",2],{"doc:\u002Fspatial-data-processing-automation\u002Fraster-analysis-workflows\u002Fclip-raster-by-mask-layer-pyqgis":3},{"id":4,"title":5,"body":6,"description":2182,"extension":2183,"meta":2184,"navigation":444,"path":2190,"seo":2191,"stem":2192,"__hash__":2193},"docs\u002Fspatial-data-processing-automation\u002Fraster-analysis-workflows\u002Fclip-raster-by-mask-layer-pyqgis\u002Findex.md","Clip a Raster by a Mask Layer in PyQGIS",{"type":7,"value":8,"toc":2165},"minimark",[9,13,38,45,340,345,375,379,397,403,407,418,580,610,614,617,656,753,769,773,786,946,971,975,986,1127,1158,1162,1168,1269,1288,1292,1295,1606,1619,1623,1636,1769,1772,1776,1779,1905,1912,1916,1923,1983,1994,1998,2059,2063,2081,2085,2094,2105,2117,2132,2136,2161],[10,11,5],"h1",{"id":12},"clip-a-raster-by-a-mask-layer-in-pyqgis",[14,15,16,17,22,23,27,28,32,33,37],"p",{},"Clipping a raster to a polygon boundary is how you restrict a DEM, satellite scene, or land-cover grid to a study area, a watershed, or an administrative unit. Unlike ",[18,19,21],"a",{"href":20},"\u002Fspatial-data-processing-automation\u002Fvector-data-manipulation\u002Fclip-vector-layer-pyqgis\u002F","clipping a vector layer",", a raster clip has to decide what happens to the pixels outside the mask: they become ",[24,25,26],"strong",{},"nodata",", and the output is usually cropped to the mask's bounding box to avoid carrying a sea of empty cells. In PyQGIS the workhorse is ",[29,30,31],"code",{},"gdal:cliprasterbymasklayer",". This is a fundamental step in ",[18,34,36],{"href":35},"\u002Fspatial-data-processing-automation\u002Fraster-analysis-workflows\u002F","Raster Analysis Workflows",".",[14,39,40,41,44],{},"This page shows a correct clip that preserves the source resolution and CRS, how to set the nodata value, how cropping to extent works, and when to reach for the ",[29,42,43],{},"native:"," equivalent instead.",[46,47,52,53,52,57,52,61,52,80,52,87,52,96,52,52,102,52,112,52,118,52,143,52,52,148,52,151,52,155,52,160,52,52,164,52,170,52,176,52,181,52,188,52,193,52,196,52,52,199,52,203,52,52,206,52,209,52,52,212,52,216,52,222,52,241,52,245,52,250,52,254,52,258,52,52,262,52,265,52,270,52,297,52,300,52,305,52,309,52,313,52,317,52,322,52,327,52,333,52,336],"svg",{"viewBox":48,"role":49,"ariaLabel":50,"xmlns":51},"0 0 820 460","img","Data-flow diagram: an input raster and a polygon mask feed gdal:cliprasterbymasklayer, which branches into two outputs depending on CROP_TO_CUTLINE","http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg","\n  ",[54,55,56],"title",{},"How gdal:cliprasterbymasklayer clips a raster by a polygon mask",[58,59,60],"desc",{},"The INPUT raster and the polygon MASK both feed the gdal:cliprasterbymasklayer algorithm, which runs with KEEP_RESOLUTION=True and NODATA=-9999. The result branches on CROP_TO_CUTLINE: when True the output grid is trimmed to the mask bounding box; when False the output keeps the full input extent and pixels outside the polygon are set to nodata.",[62,63,64,65,52],"defs",{},"\n    ",[66,67,74,75,64],"marker",{"id":68,"viewBox":69,"refX":70,"refY":71,"markerWidth":72,"markerHeight":72,"orient":73},"clip-arrow","0 0 10 10","8","5","7","auto-start-reverse","\n      ",[76,77],"path",{"d":78,"fill":79},"M0 0 L10 5 L0 10 z","#0f766e",[81,82],"rect",{"x":83,"y":83,"width":84,"height":85,"fill":86},"0","820","460","#f6f3ea",[88,89,95],"text",{"x":90,"y":91,"fill":92,"style":93,"textAnchor":94},"410","30","#17211d","text-anchor:middle;font-family:sans-serif;font-size:17px;font-weight:bold","middle","Clipping a raster by a mask layer",[88,97,101],{"x":90,"y":98,"fill":99,"style":100,"textAnchor":94},"52","#2f3b35","text-anchor:middle;font-family:sans-serif;font-size:12px","Two inputs, one clip — CROP_TO_CUTLINE decides the output shape",[81,103],{"x":104,"y":105,"width":106,"height":107,"rx":108,"fill":109,"stroke":110,"style":111},"24","74","172","132","10","#fffdf7","#2563eb","stroke-width:2",[88,113,117],{"x":114,"y":115,"fill":110,"style":116,"textAnchor":94},"110","96","text-anchor:middle;font-family:sans-serif;font-size:12px;font-weight:bold","INPUT raster",[119,120,64,122,64,128,132,134,64,136,140,52],"g",{"stroke":109,"style":121},"stroke-width:1.5",[81,123],{"x":124,"y":125,"width":126,"height":124,"fill":127},"66","108","88","#4b7f52",[129,130],"line",{"x1":126,"y1":125,"x2":126,"y2":131},"174",[129,133],{"x1":114,"y1":125,"x2":114,"y2":131},[129,135],{"x1":107,"y1":125,"x2":107,"y2":131},[129,137],{"x1":124,"y1":138,"x2":139,"y2":138},"130","154",[129,141],{"x1":124,"y1":142,"x2":139,"y2":142},"152",[88,144,147],{"x":114,"y":145,"fill":99,"style":146,"textAnchor":94},"194","text-anchor:middle;font-family:sans-serif;font-size:10px","single\u002Fmulti-band GeoTIFF",[81,149],{"x":104,"y":150,"width":106,"height":107,"rx":108,"fill":109,"stroke":79,"style":111},"248",[88,152,154],{"x":114,"y":153,"fill":79,"style":116,"textAnchor":94},"270","MASK polygon",[76,156],{"d":157,"fill":158,"stroke":79,"style":159},"M78 300 L128 288 L156 320 L134 352 L92 348 L72 322 Z","none","stroke-width:2.5;stroke-linejoin:round",[88,161,163],{"x":114,"y":162,"fill":99,"style":146,"textAnchor":94},"370","study-area boundary",[81,165],{"x":166,"y":167,"width":168,"height":138,"rx":108,"fill":109,"stroke":79,"style":169},"256","162","150","stroke-width:2.5",[88,171,175],{"x":172,"y":173,"fill":92,"style":174,"textAnchor":94},"331","192","text-anchor:middle;font-family:monospace;font-size:11px;font-weight:bold","gdal:",[88,177,180],{"x":172,"y":178,"fill":92,"style":179,"textAnchor":94},"208","text-anchor:middle;font-family:monospace;font-size:10px;font-weight:bold","cliprasterbymasklayer",[81,182],{"x":183,"y":184,"width":185,"height":104,"rx":71,"fill":186,"stroke":79,"style":187},"268","222","126","#eef4f2","stroke-width:1",[88,189,192],{"x":172,"y":190,"fill":79,"style":191,"textAnchor":94},"238","text-anchor:middle;font-family:monospace;font-size:9.5px","KEEP_RESOLUTION=True",[81,194],{"x":183,"y":195,"width":185,"height":104,"rx":71,"fill":186,"stroke":79,"style":187},"252",[88,197,198],{"x":172,"y":183,"fill":79,"style":191,"textAnchor":94},"NODATA=-9999",[76,200],{"d":201,"fill":158,"stroke":79,"style":111,"markerEnd":202},"M196 140 C 226 140, 226 200, 254 208","url(#clip-arrow)",[76,204],{"d":205,"fill":158,"stroke":79,"style":111,"markerEnd":202},"M196 314 C 226 314, 226 250, 254 246",[76,207],{"d":208,"fill":158,"stroke":79,"style":111,"markerEnd":202},"M406 200 C 440 200, 448 150, 486 150",[76,210],{"d":211,"fill":158,"stroke":79,"style":111,"markerEnd":202},"M406 254 C 440 254, 448 320, 486 320",[81,213],{"x":214,"y":105,"width":215,"height":168,"rx":108,"fill":109,"stroke":110,"style":111},"490","306",[88,217,221],{"x":218,"y":219,"fill":110,"style":220},"510","98","font-family:monospace;font-size:11px;font-weight:bold","CROP_TO_CUTLINE = True",[119,223,64,224,64,230,233,64,236,239,52],{"stroke":109,"style":121},[81,225],{"x":226,"y":227,"width":228,"height":229,"fill":127},"512","112","72","60",[129,231],{"x1":232,"y1":227,"x2":232,"y2":106},"536",[129,234],{"x1":235,"y1":227,"x2":235,"y2":106},"560",[129,237],{"x1":226,"y1":107,"x2":238,"y2":107},"584",[129,240],{"x1":226,"y1":142,"x2":238,"y2":142},[76,242],{"d":243,"fill":158,"stroke":92,"style":244},"M512 128 L548 116 L584 138 L566 170 L522 164 Z","stroke-width:2;stroke-linejoin:round",[88,246,249],{"x":247,"y":107,"fill":92,"style":248},"606","font-family:sans-serif;font-size:11px;font-weight:bold","Trimmed to bbox",[88,251,253],{"x":247,"y":168,"fill":99,"style":252},"font-family:sans-serif;font-size:10px","Output shrinks to the",[88,255,257],{"x":247,"y":256,"fill":99,"style":252},"164","mask bounding box —",[88,259,261],{"x":247,"y":260,"fill":99,"style":252},"178","no empty surround.",[81,263],{"x":214,"y":150,"width":215,"height":256,"rx":108,"fill":109,"stroke":264,"style":111},"#9aa39d",[88,266,269],{"x":218,"y":267,"fill":268,"style":220},"272","#5b655e","CROP_TO_CUTLINE = False",[119,271,64,272,64,277,64,281,284,286,64,288,291,294,52],{"stroke":109,"style":121},[81,273],{"x":226,"y":274,"width":115,"height":275,"fill":276},"286","80","#c8cdc6",[81,278],{"x":232,"y":215,"width":279,"height":280,"fill":127},"48","40",[129,282],{"x1":232,"y1":274,"x2":232,"y2":283},"366",[129,285],{"x1":235,"y1":274,"x2":235,"y2":283},[129,287],{"x1":238,"y1":274,"x2":238,"y2":283},[129,289],{"x1":226,"y1":215,"x2":290,"y2":215},"608",[129,292],{"x1":226,"y1":293,"x2":290,"y2":293},"326",[129,295],{"x1":226,"y1":296,"x2":290,"y2":296},"346",[76,298],{"d":299,"fill":158,"stroke":92,"style":244},"M524 322 L556 308 L588 330 L570 360 L530 352 Z",[88,301,304],{"x":302,"y":303,"fill":92,"style":248},"630","304","Full input extent",[88,306,308],{"x":302,"y":307,"fill":99,"style":252},"322","Grid keeps its size;",[88,310,312],{"x":302,"y":311,"fill":99,"style":252},"336","pixels outside the",[88,314,316],{"x":302,"y":315,"fill":99,"style":252},"350","polygon become",[88,318,321],{"x":302,"y":319,"fill":268,"style":320},"364","font-family:monospace;font-size:10px;font-weight:bold","NODATA",[81,323],{"x":226,"y":324,"width":325,"height":326,"fill":276,"stroke":264,"style":187},"380","16","12",[88,328,332],{"x":329,"y":330,"fill":99,"style":331},"534","390","font-family:sans-serif;font-size:9.5px","nodata fill",[81,334],{"x":335,"y":324,"width":325,"height":326,"fill":127},"600",[88,337,339],{"x":338,"y":330,"fill":99,"style":331},"622","retained data",[341,342,344],"h2",{"id":343},"what-this-recipe-covers","What This Recipe Covers",[346,347,348,352,361,364,372],"ul",{},[349,350,351],"li",{},"Running a basic clip that writes a GeoTIFF trimmed to the mask.",[349,353,354,355,357,358,37],{},"Controlling the two settings that decide the output shape and fill: ",[29,356,321],{}," and ",[29,359,360],{},"CROP_TO_CUTLINE",[349,362,363],{},"Locking the source resolution and CRS so no silent resampling creeps in.",[349,365,366,367,357,369,371],{},"Choosing between the ",[29,368,175],{},[29,370,43],{}," algorithm variants.",[349,373,374],{},"Compressing the output and clipping a whole folder of rasters to one mask.",[341,376,378],{"id":377},"prerequisites","Prerequisites",[346,380,381,384,387,390],{},[349,382,383],{},"QGIS 3.34 LTR (bundled Python 3.12) with Processing available.",[349,385,386],{},"A raster to clip (single- or multi-band GeoTIFF).",[349,388,389],{},"A polygon vector layer to use as the mask.",[349,391,392,393,396],{},"The QGIS Python Console (",[29,394,395],{},"Plugins > Python Console",").",[14,398,399,400,402],{},"The raster and the mask should share a CRS. ",[29,401,31],{}," can reproject the mask on the fly, but matching them up front avoids surprises at the boundary.",[341,404,406],{"id":405},"run-a-basic-raster-clip","Run a Basic Raster Clip",[14,408,409,410,413,414,417],{},"Provide the raster as ",[29,411,412],{},"INPUT"," and the polygon layer as ",[29,415,416],{},"MASK",". The example crops to the mask extent and writes a GeoTIFF.",[419,420,425],"pre",{"className":421,"code":422,"language":423,"meta":424,"style":424},"language-python shiki shiki-themes github-dark","import processing\n\nresult = processing.run(\"gdal:cliprasterbymasklayer\", {\n    \"INPUT\": \"\u002Fdata\u002Fdem.tif\",\n    \"MASK\": \"\u002Fdata\u002Fwatershed.gpkg|layername=basin\",\n    \"CROP_TO_CUTLINE\": True,\n    \"KEEP_RESOLUTION\": True,\n    \"NODATA\": -9999,\n    \"OUTPUT\": \"\u002Fdata\u002Foutput\u002Fdem_clipped.tif\",\n})\n\nprint(\"Clipped raster:\", result[\"OUTPUT\"])\n","python","",[29,426,427,439,446,465,480,493,507,519,535,548,554,559],{"__ignoreMap":424},[428,429,431,435],"span",{"class":129,"line":430},1,[428,432,434],{"class":433},"snl16","import",[428,436,438],{"class":437},"s95oV"," processing\n",[428,440,442],{"class":129,"line":441},2,[428,443,445],{"emptyLinePlaceholder":444},true,"\n",[428,447,449,452,455,458,462],{"class":129,"line":448},3,[428,450,451],{"class":437},"result ",[428,453,454],{"class":433},"=",[428,456,457],{"class":437}," processing.run(",[428,459,461],{"class":460},"sU2Wk","\"gdal:cliprasterbymasklayer\"",[428,463,464],{"class":437},", {\n",[428,466,468,471,474,477],{"class":129,"line":467},4,[428,469,470],{"class":460},"    \"INPUT\"",[428,472,473],{"class":437},": ",[428,475,476],{"class":460},"\"\u002Fdata\u002Fdem.tif\"",[428,478,479],{"class":437},",\n",[428,481,483,486,488,491],{"class":129,"line":482},5,[428,484,485],{"class":460},"    \"MASK\"",[428,487,473],{"class":437},[428,489,490],{"class":460},"\"\u002Fdata\u002Fwatershed.gpkg|layername=basin\"",[428,492,479],{"class":437},[428,494,496,499,501,505],{"class":129,"line":495},6,[428,497,498],{"class":460},"    \"CROP_TO_CUTLINE\"",[428,500,473],{"class":437},[428,502,504],{"class":503},"sDLfK","True",[428,506,479],{"class":437},[428,508,510,513,515,517],{"class":129,"line":509},7,[428,511,512],{"class":460},"    \"KEEP_RESOLUTION\"",[428,514,473],{"class":437},[428,516,504],{"class":503},[428,518,479],{"class":437},[428,520,522,525,527,530,533],{"class":129,"line":521},8,[428,523,524],{"class":460},"    \"NODATA\"",[428,526,473],{"class":437},[428,528,529],{"class":433},"-",[428,531,532],{"class":503},"9999",[428,534,479],{"class":437},[428,536,538,541,543,546],{"class":129,"line":537},9,[428,539,540],{"class":460},"    \"OUTPUT\"",[428,542,473],{"class":437},[428,544,545],{"class":460},"\"\u002Fdata\u002Foutput\u002Fdem_clipped.tif\"",[428,547,479],{"class":437},[428,549,551],{"class":129,"line":550},10,[428,552,553],{"class":437},"})\n",[428,555,557],{"class":129,"line":556},11,[428,558,445],{"emptyLinePlaceholder":444},[428,560,562,565,568,571,574,577],{"class":129,"line":561},12,[428,563,564],{"class":503},"print",[428,566,567],{"class":437},"(",[428,569,570],{"class":460},"\"Clipped raster:\"",[428,572,573],{"class":437},", result[",[428,575,576],{"class":460},"\"OUTPUT\"",[428,578,579],{"class":437},"])\n",[14,581,582,585,586,588,589,591,592,595,596,599,600,602,603,605,606,609],{},[24,583,584],{},"Breakdown:"," ",[29,587,412],{}," is the raster and ",[29,590,416],{}," is the polygon layer (the ",[29,593,594],{},"|layername="," suffix targets one layer inside a GeoPackage). ",[29,597,598],{},"CROP_TO_CUTLINE=True"," trims the output to the mask's bounding box; ",[29,601,192],{}," forces the output pixel size to match the source so cells stay aligned; ",[29,604,198],{}," is the value assigned to pixels outside the polygon. The output path's ",[29,607,608],{},".tif"," extension selects the GeoTIFF driver.",[341,611,613],{"id":612},"set-nodata-and-crop-behavior","Set Nodata and Crop Behavior",[14,615,616],{},"Two parameters control the shape and fill of the result, and getting them right matters for downstream statistics:",[346,618,619,637],{},[349,620,621,625,626,629,630,632,633,636],{},[24,622,623],{},[29,624,321],{}," — the value written to cells outside the mask polygon. Choose a value that cannot occur in your real data (for elevation, ",[29,627,628],{},"-9999","; for an 8-bit byte raster, ",[29,631,83],{}," or ",[29,634,635],{},"255"," if those are unused). If your source already defines a nodata value, reuse it for consistency.",[349,638,639,643,644,646,647,650,651,655],{},[24,640,641],{},[29,642,360],{}," — when ",[29,645,504],{},", the output extent shrinks to the mask's bounding box. When ",[29,648,649],{},"False",", the output keeps the ",[652,653,654],"em",{},"input"," raster's full extent and merely sets outside-the-polygon pixels to nodata, leaving a large mostly-empty grid.",[419,657,659],{"className":421,"code":658,"language":423,"meta":424,"style":424},"import processing\n\n# Keep the full input extent, only mask out the values\nprocessing.run(\"gdal:cliprasterbymasklayer\", {\n    \"INPUT\": \"\u002Fdata\u002Flandcover.tif\",\n    \"MASK\": \"\u002Fdata\u002Fcounty.gpkg\",\n    \"CROP_TO_CUTLINE\": False,\n    \"KEEP_RESOLUTION\": True,\n    \"NODATA\": 0,\n    \"OUTPUT\": \"\u002Fdata\u002Foutput\u002Flandcover_masked.tif\",\n})\n",[29,660,661,667,671,677,686,697,708,718,728,738,749],{"__ignoreMap":424},[428,662,663,665],{"class":129,"line":430},[428,664,434],{"class":433},[428,666,438],{"class":437},[428,668,669],{"class":129,"line":441},[428,670,445],{"emptyLinePlaceholder":444},[428,672,673],{"class":129,"line":448},[428,674,676],{"class":675},"sjoCn","# Keep the full input extent, only mask out the values\n",[428,678,679,682,684],{"class":129,"line":467},[428,680,681],{"class":437},"processing.run(",[428,683,461],{"class":460},[428,685,464],{"class":437},[428,687,688,690,692,695],{"class":129,"line":482},[428,689,470],{"class":460},[428,691,473],{"class":437},[428,693,694],{"class":460},"\"\u002Fdata\u002Flandcover.tif\"",[428,696,479],{"class":437},[428,698,699,701,703,706],{"class":129,"line":495},[428,700,485],{"class":460},[428,702,473],{"class":437},[428,704,705],{"class":460},"\"\u002Fdata\u002Fcounty.gpkg\"",[428,707,479],{"class":437},[428,709,710,712,714,716],{"class":129,"line":509},[428,711,498],{"class":460},[428,713,473],{"class":437},[428,715,649],{"class":503},[428,717,479],{"class":437},[428,719,720,722,724,726],{"class":129,"line":521},[428,721,512],{"class":460},[428,723,473],{"class":437},[428,725,504],{"class":503},[428,727,479],{"class":437},[428,729,730,732,734,736],{"class":129,"line":537},[428,731,524],{"class":460},[428,733,473],{"class":437},[428,735,83],{"class":503},[428,737,479],{"class":437},[428,739,740,742,744,747],{"class":129,"line":550},[428,741,540],{"class":460},[428,743,473],{"class":437},[428,745,746],{"class":460},"\"\u002Fdata\u002Foutput\u002Flandcover_masked.tif\"",[428,748,479],{"class":437},[428,750,751],{"class":129,"line":556},[428,752,553],{"class":437},[14,754,755,757,758,761,762,764,765,37],{},[24,756,584],{}," With ",[29,759,760],{},"CROP_TO_CUTLINE=False"," the file footprint matches the original raster, which is useful when several masked outputs must stay on the same grid for overlay or differencing. Set ",[29,763,321],{}," to a code that is genuinely absent from the land-cover legend so masked cells are unambiguous. The masked output is then ready for accurate summaries with ",[18,766,768],{"href":767},"\u002Fspatial-data-processing-automation\u002Fraster-analysis-workflows\u002Fcalculate-raster-statistics-pyqgis\u002F","Calculate Raster Statistics in PyQGIS",[341,770,772],{"id":771},"preserve-resolution-and-crs","Preserve Resolution and CRS",[14,774,775,777,778,781,782,785],{},[29,776,192],{}," is the safeguard against silent resampling. Without it, GDAL may snap the output to a slightly different grid, shifting pixel centers and corrupting later raster math. Pairing it with an explicit ",[29,779,780],{},"SOURCE_CRS","\u002F",[29,783,784],{},"TARGET_CRS"," keeps the projection intact:",[419,787,789],{"className":421,"code":788,"language":423,"meta":424,"style":424},"import processing\nfrom qgis.core import QgsRasterLayer\n\nraster = QgsRasterLayer(\"\u002Fdata\u002Fdem.tif\", \"dem\")\nsrc_crs = raster.crs().authid()\n\nprocessing.run(\"gdal:cliprasterbymasklayer\", {\n    \"INPUT\": \"\u002Fdata\u002Fdem.tif\",\n    \"MASK\": \"\u002Fdata\u002Fwatershed.gpkg|layername=basin\",\n    \"SOURCE_CRS\": src_crs,\n    \"TARGET_CRS\": src_crs,        # no reprojection — keep the source CRS\n    \"CROP_TO_CUTLINE\": True,\n    \"KEEP_RESOLUTION\": True,\n    \"NODATA\": -9999,\n    \"OUTPUT\": \"\u002Fdata\u002Foutput\u002Fdem_clipped.tif\",\n})\n",[29,790,791,797,810,814,835,845,849,857,867,877,885,896,906,917,930,941],{"__ignoreMap":424},[428,792,793,795],{"class":129,"line":430},[428,794,434],{"class":433},[428,796,438],{"class":437},[428,798,799,802,805,807],{"class":129,"line":441},[428,800,801],{"class":433},"from",[428,803,804],{"class":437}," qgis.core ",[428,806,434],{"class":433},[428,808,809],{"class":437}," QgsRasterLayer\n",[428,811,812],{"class":129,"line":448},[428,813,445],{"emptyLinePlaceholder":444},[428,815,816,819,821,824,826,829,832],{"class":129,"line":467},[428,817,818],{"class":437},"raster ",[428,820,454],{"class":433},[428,822,823],{"class":437}," QgsRasterLayer(",[428,825,476],{"class":460},[428,827,828],{"class":437},", ",[428,830,831],{"class":460},"\"dem\"",[428,833,834],{"class":437},")\n",[428,836,837,840,842],{"class":129,"line":482},[428,838,839],{"class":437},"src_crs ",[428,841,454],{"class":433},[428,843,844],{"class":437}," raster.crs().authid()\n",[428,846,847],{"class":129,"line":495},[428,848,445],{"emptyLinePlaceholder":444},[428,850,851,853,855],{"class":129,"line":509},[428,852,681],{"class":437},[428,854,461],{"class":460},[428,856,464],{"class":437},[428,858,859,861,863,865],{"class":129,"line":521},[428,860,470],{"class":460},[428,862,473],{"class":437},[428,864,476],{"class":460},[428,866,479],{"class":437},[428,868,869,871,873,875],{"class":129,"line":537},[428,870,485],{"class":460},[428,872,473],{"class":437},[428,874,490],{"class":460},[428,876,479],{"class":437},[428,878,879,882],{"class":129,"line":550},[428,880,881],{"class":460},"    \"SOURCE_CRS\"",[428,883,884],{"class":437},": src_crs,\n",[428,886,887,890,893],{"class":129,"line":556},[428,888,889],{"class":460},"    \"TARGET_CRS\"",[428,891,892],{"class":437},": src_crs,        ",[428,894,895],{"class":675},"# no reprojection — keep the source CRS\n",[428,897,898,900,902,904],{"class":129,"line":561},[428,899,498],{"class":460},[428,901,473],{"class":437},[428,903,504],{"class":503},[428,905,479],{"class":437},[428,907,909,911,913,915],{"class":129,"line":908},13,[428,910,512],{"class":460},[428,912,473],{"class":437},[428,914,504],{"class":503},[428,916,479],{"class":437},[428,918,920,922,924,926,928],{"class":129,"line":919},14,[428,921,524],{"class":460},[428,923,473],{"class":437},[428,925,529],{"class":433},[428,927,532],{"class":503},[428,929,479],{"class":437},[428,931,933,935,937,939],{"class":129,"line":932},15,[428,934,540],{"class":460},[428,936,473],{"class":437},[428,938,545],{"class":460},[428,940,479],{"class":437},[428,942,944],{"class":129,"line":943},16,[428,945,553],{"class":437},[14,947,948,950,951,954,955,958,959,357,961,963,964,966,967,37],{},[24,949,584],{}," Reading ",[29,952,953],{},"raster.crs().authid()"," gives the source CRS as an authority string (e.g. ",[29,956,957],{},"EPSG:32633","). Passing the same value to both ",[29,960,780],{},[29,962,784],{}," explicitly tells GDAL to clip without reprojecting, so resolution and alignment survive. To actually reproject during the clip, set a different ",[29,965,784],{}," — but for separate reprojection of many files see ",[18,968,970],{"href":969},"\u002Fspatial-data-processing-automation\u002Fcoordinate-reference-systems\u002Fbatch-reprojecting-raster-datasets\u002F","Batch Reprojecting Raster Datasets in PyQGIS",[341,972,974],{"id":973},"the-native-equivalent","The native Equivalent",[14,976,977,978,981,982,985],{},"QGIS also ships ",[29,979,980],{},"native:cliprasterbymasklayer",", a thin wrapper exposing similar options without invoking the GDAL provider directly. It is convenient when you want a ",[29,983,984],{},"TEMPORARY_OUTPUT"," layer object for chaining rather than a file on disk:",[419,987,989],{"className":421,"code":988,"language":423,"meta":424,"style":424},"import processing\n\nclipped = processing.run(\"native:cliprasterbymasklayer\", {\n    \"INPUT\": \"\u002Fdata\u002Fdem.tif\",\n    \"MASK\": \"\u002Fdata\u002Fwatershed.gpkg|layername=basin\",\n    \"SOURCE_CRS\": None,\n    \"TARGET_CRS\": None,\n    \"TARGET_EXTENT\": None,\n    \"NODATA\": -9999,\n    \"OUTPUT\": \"TEMPORARY_OUTPUT\",\n})[\"OUTPUT\"]\n\nprint(\"In-memory clip:\", clipped.width(), \"x\", clipped.height(), \"px\")\n",[29,990,991,997,1001,1015,1025,1035,1046,1056,1067,1079,1090,1100,1104],{"__ignoreMap":424},[428,992,993,995],{"class":129,"line":430},[428,994,434],{"class":433},[428,996,438],{"class":437},[428,998,999],{"class":129,"line":441},[428,1000,445],{"emptyLinePlaceholder":444},[428,1002,1003,1006,1008,1010,1013],{"class":129,"line":448},[428,1004,1005],{"class":437},"clipped ",[428,1007,454],{"class":433},[428,1009,457],{"class":437},[428,1011,1012],{"class":460},"\"native:cliprasterbymasklayer\"",[428,1014,464],{"class":437},[428,1016,1017,1019,1021,1023],{"class":129,"line":467},[428,1018,470],{"class":460},[428,1020,473],{"class":437},[428,1022,476],{"class":460},[428,1024,479],{"class":437},[428,1026,1027,1029,1031,1033],{"class":129,"line":482},[428,1028,485],{"class":460},[428,1030,473],{"class":437},[428,1032,490],{"class":460},[428,1034,479],{"class":437},[428,1036,1037,1039,1041,1044],{"class":129,"line":495},[428,1038,881],{"class":460},[428,1040,473],{"class":437},[428,1042,1043],{"class":503},"None",[428,1045,479],{"class":437},[428,1047,1048,1050,1052,1054],{"class":129,"line":509},[428,1049,889],{"class":460},[428,1051,473],{"class":437},[428,1053,1043],{"class":503},[428,1055,479],{"class":437},[428,1057,1058,1061,1063,1065],{"class":129,"line":521},[428,1059,1060],{"class":460},"    \"TARGET_EXTENT\"",[428,1062,473],{"class":437},[428,1064,1043],{"class":503},[428,1066,479],{"class":437},[428,1068,1069,1071,1073,1075,1077],{"class":129,"line":537},[428,1070,524],{"class":460},[428,1072,473],{"class":437},[428,1074,529],{"class":433},[428,1076,532],{"class":503},[428,1078,479],{"class":437},[428,1080,1081,1083,1085,1088],{"class":129,"line":550},[428,1082,540],{"class":460},[428,1084,473],{"class":437},[428,1086,1087],{"class":460},"\"TEMPORARY_OUTPUT\"",[428,1089,479],{"class":437},[428,1091,1092,1095,1097],{"class":129,"line":556},[428,1093,1094],{"class":437},"})[",[428,1096,576],{"class":460},[428,1098,1099],{"class":437},"]\n",[428,1101,1102],{"class":129,"line":561},[428,1103,445],{"emptyLinePlaceholder":444},[428,1105,1106,1108,1110,1113,1116,1119,1122,1125],{"class":129,"line":908},[428,1107,564],{"class":503},[428,1109,567],{"class":437},[428,1111,1112],{"class":460},"\"In-memory clip:\"",[428,1114,1115],{"class":437},", clipped.width(), ",[428,1117,1118],{"class":460},"\"x\"",[428,1120,1121],{"class":437},", clipped.height(), ",[428,1123,1124],{"class":460},"\"px\"",[428,1126,834],{"class":437},[14,1128,1129,1131,1132,1134,1135,1138,1139,1141,1142,1146,1147,1149,1150,1153,1154,1157],{},[24,1130,584],{}," The ",[29,1133,43],{}," variant returns a ",[29,1136,1137],{},"QgsRasterLayer"," when given ",[29,1140,984],{},", ideal for feeding the next step in a script without writing intermediate files — the same pattern used when ",[18,1143,1145],{"href":1144},"\u002Fspatial-data-processing-automation\u002Fchaining-processing-algorithms\u002Fchain-buffer-and-clip-pyqgis\u002F","chaining Processing algorithms",". The GDAL variant (",[29,1148,31],{},") exposes the full set of GDAL warp options like ",[29,1151,1152],{},"KEEP_RESOLUTION"," and creation ",[29,1155,1156],{},"OPTIONS",", so prefer it for final outputs where compression and tiling matter.",[341,1159,1161],{"id":1160},"compress-and-tile-the-output","Compress and Tile the Output",[14,1163,1164,1165,1167],{},"For deliverables, an uncompressed clipped GeoTIFF can be many times larger than necessary. Pass GDAL creation options through the ",[29,1166,1156],{}," parameter to compress and tile the result in the same step:",[419,1169,1171],{"className":421,"code":1170,"language":423,"meta":424,"style":424},"import processing\n\nprocessing.run(\"gdal:cliprasterbymasklayer\", {\n    \"INPUT\": \"\u002Fdata\u002Fdem.tif\",\n    \"MASK\": \"\u002Fdata\u002Fwatershed.gpkg|layername=basin\",\n    \"CROP_TO_CUTLINE\": True,\n    \"KEEP_RESOLUTION\": True,\n    \"NODATA\": -9999,\n    \"OPTIONS\": \"COMPRESS=DEFLATE|TILED=YES|BIGTIFF=IF_SAFER\",\n    \"OUTPUT\": \"\u002Fdata\u002Foutput\u002Fdem_clipped.tif\",\n})\n",[29,1172,1173,1179,1183,1191,1201,1211,1221,1231,1243,1255,1265],{"__ignoreMap":424},[428,1174,1175,1177],{"class":129,"line":430},[428,1176,434],{"class":433},[428,1178,438],{"class":437},[428,1180,1181],{"class":129,"line":441},[428,1182,445],{"emptyLinePlaceholder":444},[428,1184,1185,1187,1189],{"class":129,"line":448},[428,1186,681],{"class":437},[428,1188,461],{"class":460},[428,1190,464],{"class":437},[428,1192,1193,1195,1197,1199],{"class":129,"line":467},[428,1194,470],{"class":460},[428,1196,473],{"class":437},[428,1198,476],{"class":460},[428,1200,479],{"class":437},[428,1202,1203,1205,1207,1209],{"class":129,"line":482},[428,1204,485],{"class":460},[428,1206,473],{"class":437},[428,1208,490],{"class":460},[428,1210,479],{"class":437},[428,1212,1213,1215,1217,1219],{"class":129,"line":495},[428,1214,498],{"class":460},[428,1216,473],{"class":437},[428,1218,504],{"class":503},[428,1220,479],{"class":437},[428,1222,1223,1225,1227,1229],{"class":129,"line":509},[428,1224,512],{"class":460},[428,1226,473],{"class":437},[428,1228,504],{"class":503},[428,1230,479],{"class":437},[428,1232,1233,1235,1237,1239,1241],{"class":129,"line":521},[428,1234,524],{"class":460},[428,1236,473],{"class":437},[428,1238,529],{"class":433},[428,1240,532],{"class":503},[428,1242,479],{"class":437},[428,1244,1245,1248,1250,1253],{"class":129,"line":537},[428,1246,1247],{"class":460},"    \"OPTIONS\"",[428,1249,473],{"class":437},[428,1251,1252],{"class":460},"\"COMPRESS=DEFLATE|TILED=YES|BIGTIFF=IF_SAFER\"",[428,1254,479],{"class":437},[428,1256,1257,1259,1261,1263],{"class":129,"line":550},[428,1258,540],{"class":460},[428,1260,473],{"class":437},[428,1262,545],{"class":460},[428,1264,479],{"class":437},[428,1266,1267],{"class":129,"line":556},[428,1268,553],{"class":437},[14,1270,1271,585,1273,1275,1276,1279,1280,1283,1284,1287],{},[24,1272,584],{},[29,1274,1156],{}," takes pipe-separated GDAL creation flags. ",[29,1277,1278],{},"COMPRESS=DEFLATE"," shrinks the file losslessly, ",[29,1281,1282],{},"TILED=YES"," stores the raster in internal tiles for faster windowed reads, and ",[29,1285,1286],{},"BIGTIFF=IF_SAFER"," automatically switches to the BigTIFF format if the output would exceed the 4 GB classic-TIFF limit. These travel through to GDAL untouched.",[341,1289,1291],{"id":1290},"clip-many-rasters-to-one-mask","Clip Many Rasters to One Mask",[14,1293,1294],{},"When a whole folder of tiles or scenes must be clipped to the same boundary, loop over them and reuse the mask. Wrapping each call in a try\u002Fexcept keeps a single failure from stopping the batch:",[419,1296,1298],{"className":421,"code":1297,"language":423,"meta":424,"style":424},"from pathlib import Path\nimport processing\n\nsource_dir = Path(\"\u002Fdata\u002Fscenes\")\noutput_dir = Path(\"\u002Fdata\u002Fclipped\")\noutput_dir.mkdir(parents=True, exist_ok=True)\nmask = \"\u002Fdata\u002Fwatershed.gpkg|layername=basin\"\n\nfor src in sorted(source_dir.glob(\"*.tif\")):\n    out_path = output_dir \u002F f\"{src.stem}_clip.tif\"\n    try:\n        processing.run(\"gdal:cliprasterbymasklayer\", {\n            \"INPUT\": str(src),\n            \"MASK\": mask,\n            \"CROP_TO_CUTLINE\": True,\n            \"KEEP_RESOLUTION\": True,\n            \"NODATA\": -9999,\n            \"OUTPUT\": str(out_path),\n        })\n        print(f\"Clipped {src.name}\")\n    except Exception as exc:\n        print(f\"Failed {src.name}: {exc}\")\n",[29,1299,1300,1312,1318,1322,1337,1351,1375,1385,1389,1412,1442,1450,1459,1472,1480,1491,1502,1516,1529,1535,1560,1575],{"__ignoreMap":424},[428,1301,1302,1304,1307,1309],{"class":129,"line":430},[428,1303,801],{"class":433},[428,1305,1306],{"class":437}," pathlib ",[428,1308,434],{"class":433},[428,1310,1311],{"class":437}," Path\n",[428,1313,1314,1316],{"class":129,"line":441},[428,1315,434],{"class":433},[428,1317,438],{"class":437},[428,1319,1320],{"class":129,"line":448},[428,1321,445],{"emptyLinePlaceholder":444},[428,1323,1324,1327,1329,1332,1335],{"class":129,"line":467},[428,1325,1326],{"class":437},"source_dir ",[428,1328,454],{"class":433},[428,1330,1331],{"class":437}," Path(",[428,1333,1334],{"class":460},"\"\u002Fdata\u002Fscenes\"",[428,1336,834],{"class":437},[428,1338,1339,1342,1344,1346,1349],{"class":129,"line":482},[428,1340,1341],{"class":437},"output_dir ",[428,1343,454],{"class":433},[428,1345,1331],{"class":437},[428,1347,1348],{"class":460},"\"\u002Fdata\u002Fclipped\"",[428,1350,834],{"class":437},[428,1352,1353,1356,1360,1362,1364,1366,1369,1371,1373],{"class":129,"line":495},[428,1354,1355],{"class":437},"output_dir.mkdir(",[428,1357,1359],{"class":1358},"s9osk","parents",[428,1361,454],{"class":433},[428,1363,504],{"class":503},[428,1365,828],{"class":437},[428,1367,1368],{"class":1358},"exist_ok",[428,1370,454],{"class":433},[428,1372,504],{"class":503},[428,1374,834],{"class":437},[428,1376,1377,1380,1382],{"class":129,"line":509},[428,1378,1379],{"class":437},"mask ",[428,1381,454],{"class":433},[428,1383,1384],{"class":460}," \"\u002Fdata\u002Fwatershed.gpkg|layername=basin\"\n",[428,1386,1387],{"class":129,"line":521},[428,1388,445],{"emptyLinePlaceholder":444},[428,1390,1391,1394,1397,1400,1403,1406,1409],{"class":129,"line":537},[428,1392,1393],{"class":433},"for",[428,1395,1396],{"class":437}," src ",[428,1398,1399],{"class":433},"in",[428,1401,1402],{"class":503}," sorted",[428,1404,1405],{"class":437},"(source_dir.glob(",[428,1407,1408],{"class":460},"\"*.tif\"",[428,1410,1411],{"class":437},")):\n",[428,1413,1414,1417,1419,1422,1424,1427,1430,1433,1436,1439],{"class":129,"line":550},[428,1415,1416],{"class":437},"    out_path ",[428,1418,454],{"class":433},[428,1420,1421],{"class":437}," output_dir ",[428,1423,781],{"class":433},[428,1425,1426],{"class":433}," f",[428,1428,1429],{"class":460},"\"",[428,1431,1432],{"class":503},"{",[428,1434,1435],{"class":437},"src.stem",[428,1437,1438],{"class":503},"}",[428,1440,1441],{"class":460},"_clip.tif\"\n",[428,1443,1444,1447],{"class":129,"line":556},[428,1445,1446],{"class":433},"    try",[428,1448,1449],{"class":437},":\n",[428,1451,1452,1455,1457],{"class":129,"line":561},[428,1453,1454],{"class":437},"        processing.run(",[428,1456,461],{"class":460},[428,1458,464],{"class":437},[428,1460,1461,1464,1466,1469],{"class":129,"line":908},[428,1462,1463],{"class":460},"            \"INPUT\"",[428,1465,473],{"class":437},[428,1467,1468],{"class":503},"str",[428,1470,1471],{"class":437},"(src),\n",[428,1473,1474,1477],{"class":129,"line":919},[428,1475,1476],{"class":460},"            \"MASK\"",[428,1478,1479],{"class":437},": mask,\n",[428,1481,1482,1485,1487,1489],{"class":129,"line":932},[428,1483,1484],{"class":460},"            \"CROP_TO_CUTLINE\"",[428,1486,473],{"class":437},[428,1488,504],{"class":503},[428,1490,479],{"class":437},[428,1492,1493,1496,1498,1500],{"class":129,"line":943},[428,1494,1495],{"class":460},"            \"KEEP_RESOLUTION\"",[428,1497,473],{"class":437},[428,1499,504],{"class":503},[428,1501,479],{"class":437},[428,1503,1505,1508,1510,1512,1514],{"class":129,"line":1504},17,[428,1506,1507],{"class":460},"            \"NODATA\"",[428,1509,473],{"class":437},[428,1511,529],{"class":433},[428,1513,532],{"class":503},[428,1515,479],{"class":437},[428,1517,1519,1522,1524,1526],{"class":129,"line":1518},18,[428,1520,1521],{"class":460},"            \"OUTPUT\"",[428,1523,473],{"class":437},[428,1525,1468],{"class":503},[428,1527,1528],{"class":437},"(out_path),\n",[428,1530,1532],{"class":129,"line":1531},19,[428,1533,1534],{"class":437},"        })\n",[428,1536,1538,1541,1543,1546,1549,1551,1554,1556,1558],{"class":129,"line":1537},20,[428,1539,1540],{"class":503},"        print",[428,1542,567],{"class":437},[428,1544,1545],{"class":433},"f",[428,1547,1548],{"class":460},"\"Clipped ",[428,1550,1432],{"class":503},[428,1552,1553],{"class":437},"src.name",[428,1555,1438],{"class":503},[428,1557,1429],{"class":460},[428,1559,834],{"class":437},[428,1561,1563,1566,1569,1572],{"class":129,"line":1562},21,[428,1564,1565],{"class":433},"    except",[428,1567,1568],{"class":503}," Exception",[428,1570,1571],{"class":433}," as",[428,1573,1574],{"class":437}," exc:\n",[428,1576,1578,1580,1582,1584,1587,1589,1591,1593,1595,1597,1600,1602,1604],{"class":129,"line":1577},22,[428,1579,1540],{"class":503},[428,1581,567],{"class":437},[428,1583,1545],{"class":433},[428,1585,1586],{"class":460},"\"Failed ",[428,1588,1432],{"class":503},[428,1590,1553],{"class":437},[428,1592,1438],{"class":503},[428,1594,473],{"class":460},[428,1596,1432],{"class":503},[428,1598,1599],{"class":437},"exc",[428,1601,1438],{"class":503},[428,1603,1429],{"class":460},[428,1605,834],{"class":437},[14,1607,1608,585,1610,1613,1614,1618],{},[24,1609,584],{},[29,1611,1612],{},"Path.glob(\"*.tif\")"," collects the rasters, the mask path is reused for every input, and per-file error handling logs problems while the loop continues. This is the raster analog of the vector batch pattern and slots directly into a headless pipeline once you ",[18,1615,1617],{"href":1616},"\u002Fspatial-data-processing-automation\u002Fbatch-processing-with-pyqgis\u002Frun-processing-algorithm-from-script\u002F","run the Processing algorithm from a standalone script"," with Processing initialized.",[341,1620,1622],{"id":1621},"cropping-versus-masking","Cropping versus masking",[14,1624,1625,1627,1628,1631,1632,1635],{},[29,1626,31],{}," does two separable things, and the two parameters that control them are frequently confused. Cropping changes the raster's ",[652,1629,1630],{},"extent","; masking changes the ",[652,1633,1634],{},"pixel values"," outside the polygon.",[14,1637,1638],{},[46,1639,1642,1645,1648,1652,1657,1688,1707,1740],{"viewBox":1640,"role":49,"ariaLabel":1641,"xmlns":51},"0 0 760 250","A raster clipped four ways: untouched, cropped to the mask extent only, masked to nodata only, and both cropped and masked",[54,1643,1644],{},"Crop, mask, or both",[58,1646,1647],{},"Four panels show a raster with an irregular mask polygon over it. Untouched, the full raster remains. Cropped only, the extent shrinks to the mask's bounding box but the corners still hold data. Masked only, the extent is unchanged but pixels outside the polygon become nodata. Cropped and masked together gives the smallest file with only the wanted pixels.",[81,1649],{"x":83,"y":83,"width":1650,"height":1651,"fill":86},"760","250",[88,1653,1656],{"x":324,"y":1654,"style":1655,"fill":92,"textAnchor":94},"26","text-anchor:middle;font-size:14px;font-weight:bold;font-family:sans-serif","Two independent switches, four possible outputs",[119,1658,1659,1665,1671,1678,1683],{},[81,1660],{"x":326,"y":1661,"width":1662,"height":1663,"rx":108,"fill":109,"stroke":1664,"style":111},"46","176","188","#59645f",[88,1666,1670],{"x":1667,"y":1668,"style":1669,"fill":92,"textAnchor":94},"100","70","text-anchor:middle;font-size:11px;font-weight:bold;font-family:sans-serif","neither",[81,1672],{"x":1673,"y":1674,"width":1675,"height":227,"fill":110,"fillOpacity":1676,"stroke":110,"style":1677},"32","86","136",0.22,"stroke-width:1.8",[76,1679],{"d":1680,"fill":158,"stroke":1681,"style":1682},"M56 186 L58 106 L118 100 L146 142 L110 192 Z","#b45309","stroke-width:2;stroke-dasharray:5 4",[88,1684,1687],{"x":1667,"y":1685,"style":1686,"fill":99,"textAnchor":94},"220","text-anchor:middle;font-size:10.5px;font-family:sans-serif","full raster",[119,1689,1690,1693,1697,1701,1704],{},[81,1691],{"x":1692,"y":1661,"width":1662,"height":1663,"rx":108,"fill":109,"stroke":1681,"style":169},"200",[88,1694,1696],{"x":1695,"y":1668,"style":1669,"fill":1681,"textAnchor":94},"288","crop only",[81,1698],{"x":1699,"y":219,"width":1700,"height":115,"fill":110,"fillOpacity":1676,"stroke":110,"style":1677},"244","92",[76,1702],{"d":1703,"fill":158,"stroke":1681,"style":1682},"M244 186 L246 106 L306 100 L334 142 L298 192 Z",[88,1705,1706],{"x":1695,"y":1685,"style":1686,"fill":99,"textAnchor":94},"smaller extent, corners kept",[119,1708,1709,1712,1716,1729,1733,1737],{},[81,1710],{"x":1711,"y":1661,"width":1662,"height":1663,"rx":108,"fill":109,"stroke":79,"style":169},"388",[88,1713,1715],{"x":1714,"y":1668,"style":1669,"fill":79,"textAnchor":94},"476","mask only",[62,1717,1718],{},[1719,1720,1722,1725],"mask",{"id":1721},"rastMaskOnly",[81,1723],{"x":83,"y":83,"width":1650,"height":1651,"fill":1724},"#000000",[76,1726],{"d":1727,"fill":1728},"M432 186 L434 106 L494 100 L522 142 L486 192 Z","#ffffff",[81,1730],{"x":1731,"y":1674,"width":1675,"height":227,"fill":1732,"stroke":1664,"style":121},"408","#e7e2d4",[81,1734],{"x":1731,"y":1674,"width":1675,"height":227,"fill":110,"fillOpacity":1735,"style":1736},0.35,"mask:url(#rastMaskOnly)",[88,1738,1739],{"x":1714,"y":1685,"style":1686,"fill":99,"textAnchor":94},"same extent, outside = nodata",[119,1741,1742,1746,1750,1760,1763,1766],{},[81,1743],{"x":1744,"y":1661,"width":106,"height":1663,"rx":108,"fill":109,"stroke":1745,"style":169},"576","#15803d",[88,1747,1749],{"x":1748,"y":1668,"style":1669,"fill":1745,"textAnchor":94},"662","both",[62,1751,1752],{},[1719,1753,1755,1757],{"id":1754},"rastMaskBoth",[81,1756],{"x":83,"y":83,"width":1650,"height":1651,"fill":1724},[76,1758],{"d":1759,"fill":1728},"M618 186 L620 106 L680 100 L708 142 L672 192 Z",[81,1761],{"x":1762,"y":219,"width":1700,"height":115,"fill":1732,"stroke":1664,"style":121},"618",[81,1764],{"x":1762,"y":219,"width":1700,"height":115,"fill":110,"fillOpacity":1735,"style":1765},"mask:url(#rastMaskBoth)",[88,1767,1768],{"x":1748,"y":1685,"style":1686,"fill":1745,"textAnchor":94},"smallest file, wanted pixels only",[14,1770,1771],{},"\"Both\" is almost always what you want, and it is what makes the file smaller: cropping alone leaves the corner pixels present and compressible only slightly, while masking alone leaves the file the same size on disk with most of it filled by nodata.",[341,1773,1775],{"id":1774},"resolution-and-alignment","Resolution and alignment",[14,1777,1778],{},"A clip must not resample. If the output pixel grid does not line up with the input, every value in the result is an interpolation of its neighbours — which quietly invalidates any later per-pixel comparison against another dataset.",[14,1780,1781],{},[46,1782,1785,1788,1791,1794,1797,1852],{"viewBox":1783,"role":49,"ariaLabel":1784,"xmlns":51},"0 0 760 246","An aligned output grid whose cells coincide exactly with the input, compared with a shifted grid where every output pixel is a blend of four input pixels",[54,1786,1787],{},"Aligned output versus a shifted grid",[58,1789,1790],{},"On the left the output grid coincides exactly with the input grid, so each output pixel carries an original value unchanged. On the right the output grid is offset by half a pixel, so every output value is interpolated from four input pixels, and comparing the result against another dataset pixel by pixel is no longer valid.",[81,1792],{"x":83,"y":83,"width":1650,"height":1793,"fill":86},"246",[88,1795,1796],{"x":324,"y":1654,"style":1655,"fill":92,"textAnchor":94},"A clip should copy pixels, not compute new ones",[119,1798,1799,1803,1807,1845,1848],{},[81,1800],{"x":325,"y":1661,"width":1801,"height":1802,"rx":108,"fill":109,"stroke":1745,"style":169},"356","184",[88,1804,1806],{"x":145,"y":1668,"style":1805,"fill":1745,"textAnchor":94},"text-anchor:middle;font-size:12px;font-weight:bold;font-family:sans-serif","aligned",[119,1808,1811,1814,1817,1819,1821,1824,1827,1829,1831,1833,1835,1837,1839,1841,1843],{"fill":110,"fillOpacity":1809,"stroke":110,"style":1810},0.18,"stroke-width:1.2",[81,1812],{"x":275,"y":1700,"width":1813,"height":1813},"36",[81,1815],{"x":1816,"y":1700,"width":1813,"height":1813},"116",[81,1818],{"x":142,"y":1700,"width":1813,"height":1813},[81,1820],{"x":1663,"y":1700,"width":1813,"height":1813},[81,1822],{"x":1823,"y":1700,"width":1813,"height":1813},"224",[81,1825],{"x":275,"y":1826,"width":1813,"height":1813},"128",[81,1828],{"x":1816,"y":1826,"width":1813,"height":1813},[81,1830],{"x":142,"y":1826,"width":1813,"height":1813},[81,1832],{"x":1663,"y":1826,"width":1813,"height":1813},[81,1834],{"x":1823,"y":1826,"width":1813,"height":1813},[81,1836],{"x":275,"y":256,"width":1813,"height":1813},[81,1838],{"x":1816,"y":256,"width":1813,"height":1813},[81,1840],{"x":142,"y":256,"width":1813,"height":1813},[81,1842],{"x":1663,"y":256,"width":1813,"height":1813},[81,1844],{"x":1823,"y":256,"width":1813,"height":1813},[81,1846],{"x":1816,"y":1826,"width":125,"height":228,"fill":158,"stroke":1745,"style":1847},"stroke-width:3",[88,1849,1851],{"x":145,"y":1685,"style":1850,"fill":1745,"textAnchor":94},"text-anchor:middle;font-size:11px;font-family:sans-serif","values copied unchanged",[119,1853,1854,1857,1861,1897,1901],{},[81,1855],{"x":1711,"y":1661,"width":1801,"height":1802,"rx":108,"fill":109,"stroke":1856,"style":169},"#b91c1c",[88,1858,1860],{"x":1859,"y":1668,"style":1805,"fill":1856,"textAnchor":94},"566","shifted",[119,1862,1863,1866,1869,1872,1874,1877,1879,1881,1883,1885,1887,1889,1891,1893,1895],{"fill":110,"fillOpacity":1809,"stroke":110,"style":1810},[81,1864],{"x":1865,"y":1700,"width":1813,"height":1813},"452",[81,1867],{"x":1868,"y":1700,"width":1813,"height":1813},"488",[81,1870],{"x":1871,"y":1700,"width":1813,"height":1813},"524",[81,1873],{"x":235,"y":1700,"width":1813,"height":1813},[81,1875],{"x":1876,"y":1700,"width":1813,"height":1813},"596",[81,1878],{"x":1865,"y":1826,"width":1813,"height":1813},[81,1880],{"x":1868,"y":1826,"width":1813,"height":1813},[81,1882],{"x":1871,"y":1826,"width":1813,"height":1813},[81,1884],{"x":235,"y":1826,"width":1813,"height":1813},[81,1886],{"x":1876,"y":1826,"width":1813,"height":1813},[81,1888],{"x":1865,"y":256,"width":1813,"height":1813},[81,1890],{"x":1868,"y":256,"width":1813,"height":1813},[81,1892],{"x":1871,"y":256,"width":1813,"height":1813},[81,1894],{"x":235,"y":256,"width":1813,"height":1813},[81,1896],{"x":1876,"y":256,"width":1813,"height":1813},[81,1898],{"x":1899,"y":1900,"width":125,"height":228,"fill":158,"stroke":1856,"style":1847},"506","146",[88,1902,1904],{"x":1859,"y":1903,"style":1850,"fill":1856,"textAnchor":94},"228","every value interpolated",[14,1906,1907,1908,1911],{},"The practical defence is to leave the target resolution unset so GDAL inherits the source grid, and to compare ",[29,1909,1910],{},"rasterUnitsPerPixelX()"," on input and output afterwards. A difference of even a fraction of a unit means resampling happened.",[341,1913,1915],{"id":1914},"qgis-version-compatibility","QGIS Version Compatibility",[14,1917,1918,1919,1922],{},"The code targets ",[24,1920,1921],{},"QGIS 3.34 LTR"," (Python 3.12).",[1924,1925,1926,1942],"table",{},[1927,1928,1929],"thead",{},[1930,1931,1932,1936,1939],"tr",{},[1933,1934,1935],"th",{},"QGIS version",[1933,1937,1938],{},"Python",[1933,1940,1941],{},"Notes",[1943,1944,1945,1962,1973],"tbody",{},[1930,1946,1947,1951,1954],{},[1948,1949,1950],"td",{},"3.28 LTR",[1948,1952,1953],{},"3.9",[1948,1955,1956,1958,1959,1961],{},[29,1957,31],{}," identical; ",[29,1960,43],{}," variant present.",[1930,1963,1964,1967,1970],{},[1948,1965,1966],{},"3.34 LTR",[1948,1968,1969],{},"3.12",[1948,1971,1972],{},"Baseline for this page.",[1930,1974,1975,1978,1980],{},[1948,1976,1977],{},"3.40 \u002F 3.44",[1948,1979,1969],{},[1948,1981,1982],{},"Same algorithm IDs and parameters; newer GDAL improves nodata handling.",[14,1984,1985,1986,828,1988,1990,1991,1993],{},"Both algorithm IDs and their ",[29,1987,360],{},[29,1989,1152],{},", and ",[29,1992,321],{}," parameters are stable across the current 3.x line. The exact GDAL version bundled differs per release, which can affect edge-pixel handling on very large rasters, but the PyQGIS interface is unchanged.",[341,1995,1997],{"id":1996},"troubleshooting","Troubleshooting",[346,1999,2000,2006,2020,2034,2047],{},[349,2001,2002,2005],{},[24,2003,2004],{},"Output is all nodata."," The mask does not overlap the raster, or their CRS differ so the polygon lands outside the raster footprint. Confirm both extents intersect in a common CRS.",[349,2007,2008,585,2011,2013,2014,2016,2017,2019],{},[24,2009,2010],{},"Pixels look shifted after clipping.",[29,2012,1152],{}," was ",[29,2015,649],{},", letting GDAL resample to a new grid. Set it to ",[29,2018,504],{}," to preserve the source cell size and alignment.",[349,2021,2022,585,2025,2027,2028,2030,2031,2033],{},[24,2023,2024],{},"Output extent is huge and mostly empty.",[29,2026,360],{}," is ",[29,2029,649],{},". Set it ",[29,2032,504],{}," to trim the output to the mask's bounding box.",[349,2035,2036,2039,2040,2042,2043,2046],{},[24,2037,2038],{},"Statistics include the fill value."," The clip's ",[29,2041,321],{}," was not recognized downstream. Verify with ",[29,2044,2045],{},"gdalinfo"," that the output declares the nodata value, and reuse the source's existing nodata when possible.",[349,2048,2049,2054,2055,2058],{},[24,2050,2051,37],{},[29,2052,2053],{},"Mask layer geometry invalid"," Self-intersecting mask polygons can break the cutline. Run ",[29,2056,2057],{},"native:fixgeometries"," on the mask first.",[341,2060,2062],{"id":2061},"conclusion","Conclusion",[14,2064,2065,2066,2068,2069,2071,2072,2074,2075,2077,2078,2080],{},"Clipping a raster by a mask in PyQGIS is reliable once three settings are deliberate: a ",[29,2067,321],{}," value that cannot collide with real data, ",[29,2070,360],{}," to control whether the output is trimmed or kept full-extent, and ",[29,2073,1152],{}," to stop GDAL from silently resampling. Use ",[29,2076,31],{}," for final, compressed file outputs and the ",[29,2079,43],{}," variant when you want an in-memory layer to chain. Keeping the raster and mask in the same CRS ties it all together and produces clean, analysis-ready clips.",[341,2082,2084],{"id":2083},"frequently-asked-questions","Frequently Asked Questions",[14,2086,2087,2090,2091,2093],{},[24,2088,2089],{},"What value should I use for NODATA?","\nPick a number that cannot appear in your real data — ",[29,2092,628],{}," for elevation, or an unused legend code for categorical rasters. If the source already declares a nodata value, reuse it so masked cells stay consistent through the pipeline.",[14,2095,2096,2099,2101,2102,2104],{},[24,2097,2098],{},"What is the difference between CROP_TO_CUTLINE True and False?",[29,2100,504],{}," shrinks the output to the mask's bounding box, dropping the empty surround. ",[29,2103,649],{}," keeps the input raster's full extent and only sets outside-the-polygon pixels to nodata, leaving a larger, mostly-empty grid useful for keeping multiple outputs on one grid.",[14,2106,2107,2110,2111,2113,2114,2116],{},[24,2108,2109],{},"How do I keep the original resolution?","\nSet ",[29,2112,1152],{}," to ",[29,2115,504],{},". Otherwise GDAL may snap the output to a slightly different grid, shifting pixel centers and breaking later raster algebra.",[14,2118,2119,2122,2123,2125,2126,2128,2129,2131],{},[24,2120,2121],{},"When should I use the native variant instead of the GDAL one?","\nUse ",[29,2124,980],{}," with ",[29,2127,984],{}," when you want an in-memory layer to feed straight into the next algorithm. Use ",[29,2130,31],{}," for final files where you need GDAL options like compression, tiling, and explicit resolution control.",[341,2133,2135],{"id":2134},"related","Related",[346,2137,2138,2143,2147,2151,2156],{},[349,2139,2140,2141],{},"Up to parent: ",[18,2142,36],{"href":35},[349,2144,2145],{},[18,2146,768],{"href":767},[349,2148,2149],{},[18,2150,970],{"href":969},[349,2152,2153],{},[18,2154,2155],{"href":20},"Clip a Vector Layer in PyQGIS",[349,2157,2158],{},[18,2159,2160],{"href":1616},"Run a Processing Algorithm from a Script",[2162,2163,2164],"style",{},"html pre.shiki code .snl16, html code.shiki .snl16{--shiki-default:#F97583}html pre.shiki code .s95oV, html code.shiki .s95oV{--shiki-default:#E1E4E8}html pre.shiki code .sU2Wk, html code.shiki .sU2Wk{--shiki-default:#9ECBFF}html pre.shiki code .sDLfK, html code.shiki .sDLfK{--shiki-default:#79B8FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .sjoCn, html code.shiki .sjoCn{--shiki-default:#9AA79F}html pre.shiki code .s9osk, html code.shiki .s9osk{--shiki-default:#FFAB70}",{"title":424,"searchDepth":441,"depth":441,"links":2166},[2167,2168,2169,2170,2171,2172,2173,2174,2175,2176,2177,2178,2179,2180,2181],{"id":343,"depth":441,"text":344},{"id":377,"depth":441,"text":378},{"id":405,"depth":441,"text":406},{"id":612,"depth":441,"text":613},{"id":771,"depth":441,"text":772},{"id":973,"depth":441,"text":974},{"id":1160,"depth":441,"text":1161},{"id":1290,"depth":441,"text":1291},{"id":1621,"depth":441,"text":1622},{"id":1774,"depth":441,"text":1775},{"id":1914,"depth":441,"text":1915},{"id":1996,"depth":441,"text":1997},{"id":2061,"depth":441,"text":2062},{"id":2083,"depth":441,"text":2084},{"id":2134,"depth":441,"text":2135},"Clip a raster by a polygon mask in PyQGIS with gdal:cliprasterbymasklayer. Set nodata, crop to extent, and keep the original resolution and CRS.","md",{"slug":2185,"type":2186,"breadcrumb":2187,"datePublished":2188,"dateModified":2189},"clip-raster-by-mask-layer-pyqgis","article","Clip Raster by Mask Layer","2025-08-14","2026-07-18","\u002Fspatial-data-processing-automation\u002Fraster-analysis-workflows\u002Fclip-raster-by-mask-layer-pyqgis",{"title":5,"description":2182},"spatial-data-processing-automation\u002Fraster-analysis-workflows\u002Fclip-raster-by-mask-layer-pyqgis\u002Findex","N9b2qjc2zPpNtCLqwrkVrz1iCT9D5_tqXHp6Lf7r6JQ",1787823363776]