Extract Slope Values to Points

Topographic Analysis · Wetness, Slope and Extreme Values · geoprocessing tool · by Jeff Jenness
Works at every ArcGIS Pro license level

Summary

Adds a field holding the slope at each point, read from a slope raster, to a copy of a point feature class or to the feature class itself. This tool is nearly identical to Esri's Extract Values to Points, except that it correctly interpolates percent slope values, it can add the field to the existing point features if you want, and it needs no license for any extension. The raster can also be a DEM: the tool then computes the slope itself at each point, by Horn's 3 × 3 method (the method of Esri's Slope tool) or a least-squares quadratic over a window you choose, with the distances between cells measured on the spheroid in any coordinate system (see Computing from a DEM).

Learn more Why slope statistics belong in angle space, on the Slope Zonal Statistics as Table page, explains why a percent-slope raster cannot be averaged as it stands and tabulates how large the error gets. The Slope Graphic page covers the same ground for the statistics of a slope graphic.

What is different about slope

Esri's Extract Values to Points, with interpolation switched on, averages the four cell values around a point as plain numbers. That is the right thing for elevation, temperature or any raster whose values can be added together. A percent-slope raster is different. Percent slope is 100 times the rise over the run, and rise over run is the tangent of the slope angle, so the raster holds tangents. The tangent grows faster and faster as the angle steepens: 45° is 100%, 70° is 275%, and 85° is 1,143%. Average two tangents and the steeper one pulls the result up more than the gentler one pulls it down, so an interpolated value made from raw percents comes out too steep. A point midway between a 50° cell and a 70° cell lies on ground whose slope is 60°, which is 173.2%. The mean of the two percent values is 197.0%, which is a 63.1° slope, three degrees too steep.

Slope anglePercent slope
One cell50°119.2%
The other cell70°274.7%
Mean of the angles60°173.2%
Mean of the percents63.1°197.0%

The error is small on gentle ground and grows with steepness and with the contrast between neighboring cells; the Slope Zonal Statistics as Table page tabulates it for pairs of slopes from 10° to 89°. A raster in degrees has no such problem, because the angle is the quantity being averaged.

This tool therefore interpolates on the angles. With interpolation on, each of the four cell centers around the point is converted to its slope angle: the arctangent of the percent divided by 100, or of the rise:run ratio; a rescaling for gradians; nothing at all for degrees. The angles are combined with the standard bilinear weights, and the result is converted back to the raster's unit. For a percent-slope raster:

θ¯ = ∑i=14 wi ⁢ arctan ( pi100 ) , value = 100 ⁢ tan θ¯

where pi is the percent slope of each of the four surrounding cell centers and wi its bilinear weight, which depends on how close the point lies to that cell center; the four weights sum to one. A degree raster and a percent raster of the same ground give the same answer, one as an angle and the other as its tangent times 100.

Two ways to extract

The Interpolate checkbox chooses between two readings of the raster, and the default matches Esri's default:

Units and how they are detected

The Slope units of the input raster drop-down names the unit the raster's values are in, the same four choices as the Slope Zonal Statistics as Table tool:

The tool fills this in for you when it can. Esri's Slope and Surface Parameters tools record their output unit (DEGREE or PERCENT_RISE) in the geoprocessing history stored in the raster's metadata, and the tool reads that history when you pick a raster and sets the drop-down to match. When the history says nothing, the drop-down falls back to Degrees.

If the history records one unit and you choose another, the drop-down shows a warning, the tool runs with the unit you chose, and the same warning is written to the run report and into the new field's metadata. The history can only ever say degrees or percent, because those are the two units Esri's tools write, so choosing rise:run or gradians for a raster that has a history draws the warning too. It is still the right choice for a raster that really is in one of those units; the warning is there to make you look.

Values beyond ±90 for degrees, or ±100 for gradians, cannot be slopes in that unit, which is what a percent-slope raster looks like when it is read as degrees. The tool counts such cells among the ones it sampled and warns that the raster may not be a slope raster in the chosen unit. With interpolation on, those cells are left out of the interpolation like NoData; with interpolation off, a point on such a cell receives the stored value anyway, since nothing is being computed. Percent and rise:run have no limit, so nothing is excluded on those grounds.

Computing from a DEM

Set What the raster holds to Elevation (DEM) and the tool computes the slope itself, at exactly the cells the extraction needs, so the numbers are the same as making a slope raster first and extracting from it. Two methods are offered.

How the two methods differ

Both methods estimate the same two numbers at the center cell, the east–west and north–south gradients ∂z/∂x and ∂z/∂y, and both then turn them into slope in the same way. They differ in how the gradients are estimated from the neighboring cells. Number the cells of the 3 × 3 window around the center cell z5:

z1z2z3
z4z5z6
z7z8z9

Horn's method is a finite difference: a fixed recipe of weights. The east–west gradient is the difference between the east column and the west column, with the middle cell of each column counted twice and the corners once, divided by eight cell widths h (the north–south gradient is the same recipe applied to the top and bottom rows). The center cell itself is not used.

∂z∂x = (z3+2z6+z9) − (z1+2z4+z7) 8h (Horn)

The quadratic method is a surface fit. A quadratic surface, z = ax² + by² + cxy + dx + ey + f, is fitted to the cells of the window by least squares — it passes as close as it can to all of them, not exactly through any — and the gradients are the fitted surface's own gradients at the center, the coefficients d and e. The fit uses every cell in the window, the center included, and it also yields the surface's curvatures, which this tool does not need. Applied to the 3 × 3 window, the least-squares fit works out to a finite difference of its own, the Evans–Young estimator: the same column differences as Horn's, with every cell weighted equally and the sum divided by six cell widths.

∂z∂x = (z3+z6+z9) − (z1+z4+z7) 6h (quadratic, 3 × 3)

So at 3 × 3 the two methods differ only in whether the four orthogonal neighbors count double. Horn's weights put more trust in the nearest cells and less in the corners, which is why Horn is a little more accurate on an error-free surface and a little more sensitive to a bad cell (the table below); on real DEMs the two agree closely, and for a plane they are identical. The real difference appears when the quadratic window is widened. A 5 × 5 or 15 × 15 fit takes in 25 or 225 cells, so its gradient is the gradient of a surface averaged over that footprint: individual noisy cells have little say, and features smaller than the window are smoothed out, which is exactly what Esri's Surface Parameters neighborhood distance does and what Wood (1996) and Evans (2013) recommend for fine-resolution DEMs. Horn's method has no such setting; its footprint is always the 3 × 3 window, which Hodgson (1995) showed represents an area roughly twice the cell size.

Which to choose. Horn's method is the right default: it is what every slope raster made with Esri's Slope tool, GRASS, and most other software already contains, so values computed here from the DEM agree with values extracted from such rasters, and it is the better-tested estimator on ordinary 10 to 30 m DEMs. The quadratic method earns its place when the DEM is much finer than the terrain features of interest — a 1 m lidar DEM on which a 3 × 3 slope is the slope of a tussock or a furrow — or when the question is the slope of the hillside at a chosen scale rather than at the cell; a window of 5 to 15 cells gives the slope of the surface averaged over that footprint, with the noise of individual cells averaged away. The quadratic at 3 × 3 is rarely wanted on its own account; it is offered so that the method is complete and so that a user who needs the Evans–Young estimator, the one SAGA and several research codes use, has it.

Horn's method is kept as the default for a reason beyond matching Esri. Every comparison of 3 × 3 slope estimators since Skidmore (1989) has found it a highly accurate estimator in practice: Jones (1998) ranked it second only to the four-cell method on an error-free surface, Florinsky (1998) and Zhou and Liu (2004) showed that the eight-neighbor estimators are the least sensitive to errors in the DEM, and Evans (2013) summarized the literature as favoring the nine-point quadratic family, of which Horn's weights are a member. Zhou and Liu's error model makes the trade-off explicit:

EstimatorSlope RMSE, error-free surfaceAspect RMSE, error-freeSensitivity to DEM error, relative to Horn
Four-cell (Fleming and Hoffer 1979; Zevenbergen and Thorne 1987; Esri's biquadratic at 3 × 3)0.22°0.13°1.63×
Horn (1981) — Esri's Slope and Aspect tools; this tool's default0.36°0.12°1.00×
Equal-weight six-cell (Sharpnack and Akin 1969; the Evans–Young quadratic, Esri's quadratic and this tool's quadratic at 3 × 3)0.41°0.20°0.94×

From Zhou and Liu (2004), Tables 2–4: the root-mean-square errors of the three 3 × 3 estimators on an error-free analytic surface (an inverse ellipsoid, 10 m cells), and the coefficient by which each passes DEM error into the slope, scaled to Horn's. The four-cell estimator is the most accurate on perfect data and the most sensitive to error; the equal-weight estimator is the least sensitive and the least accurate; Horn's weights sit between them on both counts.

Esri's Surface Parameters tool fits its quadratic or biquadratic surface in geocentric coordinates, a different arithmetic from the planar fit here. To extract values computed exactly as Surface Parameters computes them, run Surface Parameters first and extract from its raster with What the raster holds left at Slope values.

Elevation units default from the DEM's vertical coordinate system when it has one, and are locked; when the DEM gives nothing to go on, choose Meters or Feet yourself, since a wrong unit scales every slope value. The Slope units drop-down then gives the unit of the computed values, degrees, percent, rise:run or gradians, and the interpolation is still done on the angles.

Where the values go

The Where to write the values drop-down offers two choices:

In either case the new field is a DOUBLE named Slope unless you choose another name. A name that is not valid for the workspace, or is already taken, is adjusted to Slope_2, Slope_3 and so on; the dialog warns when the input already has a field of that name, and the run messages report the name actually used. The values are in the raster's unit. A point that falls on NoData or outside the raster gets NULL in a geodatabase; a shapefile cannot store NULL in a number field, so it gets −9999 there. The field's own metadata records the unit, the NULL or −9999 convention, whether the value was interpolated, the source raster and any unit warning, so the meaning of the numbers travels with the data.

The metadata of the field Slope: alias Slope, data type Double, and a field description reading Slope at the point, in percent (the unit of the source raster, Percent slope (rise/run times 100)); NULL = NoData or outside the raster. Method: Bilinear interpolation of the four surrounding cell centers computed on the slope angles (each cell converted to degrees, averaged, converted back; NoData and out-of-range neighbors excluded). Source raster: Flagstaff_Percent_Slope. Description source: Jenness Enterprises
The new field's metadata, as the feature class's metadata shows it: the unit, the NULL convention, the method and the source raster.

When the values go into the input, the tool's derived output, Updated input point features, carries the input with its new field to the next tool in a model.

Coordinate systems

The points are read in the raster's coordinate system. Point coordinates can be reprojected exactly, while projecting a raster resamples every cell and damages the values, so the raster is never projected, and the points and raster may be in different coordinate systems without harm. When the two are on different datums, such as NAD27 points on a NAD83 raster, the points are moved with a datum transformation as well, and the run messages name the transformation used; without one, points can land 100 m or more from their true cells. The raster is read only over the extent of the points, with a margin of cells around it, so a regional raster with a small cluster of points is handled quickly. Projected and geographic rasters both work, since a point's containing cell and its four neighboring cell centers are found the same way in either. See Projecting Rasters for why the raster is left alone.

A tour of the dialog

The dialog asks for the points, the slope raster, and where to write the values; for a new feature class, an output name is suggested from the input, and for the input itself the output name row disappears. Below those are the Interpolate checkbox, the output field name, and the units drop-down, which fills itself in from the raster's history when it can and warns when your choice disagrees with it. The checkbox and field name are remembered from run to run; the write-to choice always starts at a new feature class.

The Topographic Analysis Tools gallery open on the ribbon, with the Extract Slope Values to Points button, in the Wetness, Slope and Extreme Values row, outlined in blue
Where to find it: Extract Slope Values to Points is in the Wetness, Slope and Extreme Values row of the Topographic Analysis Tools gallery, in the Topographic Analysis group of the Wildlife and Forestry tab.
The Extract Slope Values to Points pane: Input point features Slope_at_Springs, Input slope raster or DEM Flagstaff_Percent_Slope, What the raster holds set to Slope values, Where to write the values set to A new point feature class (a copy of the input), Output point features Slope_at_Springs_Slope, Interpolate values checked, Output field name Slope, Slope units Percent slope (rise/run × 100).
The dialog with the springs feature class as the points and a percent-slope raster of the Flagstaff area. What the raster holds stays at Slope values; the units drop-down read Percent slope from the raster's geoprocessing history on its own, and the values go to a new feature class, Slope_at_Springs_Slope.
The Extract Slope Values to Points pane over a map of springs on the slope raster, with Slope units of the input raster changed to Degrees (-90 to 90) and a warning icon beside it; the parameter's help pop-up reads: Warning. The raster's geoprocessing history records its values as percent slope, but the unit chosen is 'Degrees (-90 to 90)'. The values are read as degrees, as chosen; make sure that is what you want.
The same pane with the units drop-down changed to Degrees (-90 to 90): a warning icon appears beside the parameter, and its pop-up help says that the raster's history records percent slope while the unit chosen is degrees. The tool still runs with the unit you chose.
Seventeen springs on the percent-slope raster of the Flagstaff area, each labeled with its slope in percent: 4%, 7% and 9% on the gentler ground, 28%, 29%, 30% and 45% on the slopes, and 78% on the steepest mountainside
Some of the output points over the slope raster, labeled with their new Slope field rounded to whole percent: a few percent on the gentler ground, 78% on the steepest mountainside.
The Extract Slope Values to Points run report, Messages tab: a warning that the points (GCS_WGS_1984) and the slope raster (GCS_North_American_1983) are on different datums and the points were projected onto the raster with the transformation WGS_1984_(ITRF00)_To_NAD_1983; the ImportToolbox scripting hint; Sampled 85 points: 85 with a value, 0 on NoData or outside the raster (NULL); Values are in percent: each point's value is a bilinear interpolation of the four surrounding cell centers computed on the slope ANGLES and converted back to percent; Extract Slope Values to Points complete; elapsed time 10.24 seconds
The run report: the datum transformation used to move the WGS 84 springs onto the NAD 83 raster, how many points received a value and how many fell on NoData or outside the raster, and the unit and method behind the values. No unit warning appears here because this run used the unit the history records; a mismatch is reported in the same place.

Choosing Elevation (DEM) in What the raster holds changes the pane: the units row becomes the unit of the computed values and three rows appear for the method, the window size (quadratic method only) and the elevation units, the last filled in and locked when the DEM has a vertical coordinate system.

The same pane with DEM_Flagstaff_Area as the raster and What the raster holds set to Elevation (DEM): Output point features Slope_at_Springs_from_DEM, Slope units Degrees (-90 to 90), Method Horn (3 x 3; the method of Esri's Slope and Aspect tools), Elevation units Meters.
The same points with the DEM DEM_Flagstaff_Area as the raster and What the raster holds set to Elevation (DEM). The units row now names the unit of the computed values, degrees here, and two rows appear below it for the method, Horn's 3 × 3, and the DEM's elevation units; the window-size row appears only when the quadratic method is chosen. The values go to Slope_at_Springs_from_DEM.

ModelBuilder

A ModelBuilder diagram: World_Springs and Flagstaff_Percent_Slope feed Extract Slope Values to Points, which has two output elements, Slope_at_Springs and World_Springs (2)
Extract Slope Values to Points in a model, with its two output elements: the new feature class, Slope_at_Springs, and the derived World_Springs (2), which is the input itself when the values are written into it.

In a model the tool behaves like Esri's: the output feature class is the element to connect onward. When the values go into the input, connect the derived Updated input point features element instead.

Parameters

LabelExplanationData type
Input point featuresRequired · in_points The points to extract slope for. An active selection and a definition query are honored. Single-point features only; multipoint feature classes are not accepted. Feature Layer
Input slope raster or DEM (single band)Required · in_raster A single-band slope raster in degrees, percent slope, rise:run ratio or gradians (the unit is read from the raster's geoprocessing history when it is recorded there and set in the units drop-down), or a DEM with the next parameter set to Elevation (DEM). Raster Layer
What the raster holdsRequired · surface_type Slope values, the default, or Elevation (DEM), which makes the tool compute the slope from the elevations by the method chosen below (see Computing from a DEM). String
Where to write the valuesRequired · write_to A new point feature class (a copy of the input), the default, or A new field in the input feature class, which adds the field to the input itself and disables the output name. String
Output point featuresOptional · out_points The new point feature class: a copy of the input points with all their attributes plus the new slope field. A name is suggested from the input. Required when the values go to a new feature class; ignored when they go into the input. Feature Class
Interpolate values at the point locations (bilinear, on the slope angles)Optional · interpolate Unchecked (default): each point gets the value of the cell it falls in, as stored. Checked: each point gets the bilinear interpolation of the four surrounding cell centers computed on the slope angles and converted back to the raster's unit, with NoData and out-of-range neighbors left out and the weights renormalized. Boolean
Output field nameOptional · field_name The name of the new DOUBLE field. Default Slope; adjusted if the name is not valid for the workspace or is already in use, with a warning in the dialog when the input already has a field of that name. String
Slope units (of the raster, or of the values computed from a DEM)Required · slope_units Degrees (-90 to 90), Percent slope (rise/run × 100), Rise:run ratio or Gradians (gons). For a slope raster: set from its geoprocessing history when it records a unit, otherwise Degrees, and a choice that disagrees with the history draws a warning here and in the run report (the tool runs with the choice). For a DEM: the unit of the computed values. String
Method (from a DEM)Optional · slope_method Only when the raster is a DEM. Horn (3 x 3; the method of Esri's Slope and Aspect tools), the default, or Quadratic least squares (choose the window size); see Computing from a DEM. String
Window size in cells (quadratic method)Optional · window_size 3, 5, 7, 9, 11, 13 or 15 cells on a side for the quadratic fit; Horn's method is always 3 × 3. Default 3. Long
Elevation units (from a DEM)Optional · elev_units Meters or Feet. Filled in and locked from the DEM's vertical coordinate system when it has one; otherwise choose, since a wrong unit scales every value. String
Updated input point featuresDerived · updated_points For ModelBuilder: the input point features with their new field, filled in when the values are written into the input feature class and empty when a new feature class is made. Feature Layer

Python

interpolate is True or False. The write_to strings are exactly "A new point feature class (a copy of the input)" and "A new field in the input feature class"; the slope_units strings are exactly "Degrees (-90 to 90)", "Percent slope (rise/run × 100)", "Rise:run ratio" and "Gradians (gons)". The surface_type strings are "Slope values" and "Elevation (DEM)", and the slope_method strings "Horn (3 x 3; the method of Esri's Slope and Aspect tools)" and "Quadratic least squares (choose the window size)". The new field is DOUBLE, in the raster's unit; NULL (geodatabase) or −9999 (shapefile) is NoData or outside the raster.

import arcpy
arcpy.ImportToolbox(r"C:\path\to\JennessEnterprisesTools.pyt")  # your installed path is shown in this tool's run messages

# Value of the cell each point falls in, written to a copy of the points
arcpy.jenness.ExtractSlopeValuesToPoints(
    in_points=r"C:\Project\Wildlife.gdb\telemetry_points",
    in_raster=r"C:\Project\Terrain.gdb\slope_percent",
    surface_type="Slope values",
    write_to="A new point feature class (a copy of the input)",
    out_points=r"C:\Project\Wildlife.gdb\telemetry_points_Slope",
    interpolate=False,
    field_name="Slope",
    slope_units="Percent slope (rise/run × 100)")

# Angle-space bilinear interpolation, written into the input feature class
arcpy.jenness.ExtractSlopeValuesToPoints(
    in_points=r"C:\Project\Wildlife.gdb\telemetry_points",
    in_raster=r"C:\Project\Terrain.gdb\slope_percent",
    surface_type="Slope values",
    write_to="A new field in the input feature class",
    interpolate=True,
    field_name="Slope_Pct",
    slope_units="Percent slope (rise/run × 100)")

# Slope straight from a DEM: Horn's 3 x 3 method, the numbers Esri's Slope tool gives
arcpy.jenness.ExtractSlopeValuesToPoints(
    in_points=r"C:\Project\Wildlife.gdb\telemetry_points",
    in_raster=r"C:\Project\Terrain.gdb\dem",
    surface_type="Elevation (DEM)",
    write_to="A new field in the input feature class",
    interpolate=False,
    field_name="Slope",
    slope_units="Degrees (-90 to 90)",
    slope_method="Horn (3 x 3; the method of Esri's Slope and Aspect tools)",
    elev_units="Meters")

# Quadratic least squares over a 7 x 7 window, smoother on a fine lidar DEM
arcpy.jenness.ExtractSlopeValuesToPoints(
    in_points=r"C:\Project\Wildlife.gdb\telemetry_points",
    in_raster=r"C:\Project\Terrain.gdb\dem",
    surface_type="Elevation (DEM)",
    write_to="A new point feature class (a copy of the input)",
    out_points=r"C:\Project\Wildlife.gdb\telemetry_points_Slope",
    interpolate=True,
    field_name="Slope",
    slope_units="Percent slope (rise/run × 100)",
    slope_method="Quadratic least squares (choose the window size)",
    window_size=7,
    elev_units="Meters")

Recommended citation

Jenness, J. 2026. Extract Slope Values to Points. Wildlife and Forestry Tools add-in for ArcGIS Pro, v. 1.113.62.1 (October 2026). Jenness Enterprises. Available at: https://github.com/JeffJenness/Wildlife_Tools.

Credits and references

By Jeff Jenness, Jenness Enterprises (www.jennessent.com). The tool is modeled on Esri's Extract Values to Points; the angle-space interpolation applies the rule of the Slope Zonal Statistics as Table tool to a single point. The DEM option uses Horn's (1981) gradient, the method of Esri's Slope tool, or the Evans–Young quadratic described by Evans (2013); the comparison of estimators is from Zhou and Liu (2004), with Skidmore (1989), Jones (1998) and Florinsky (1998) as the earlier tests.

Licensing information

Works at every ArcGIS Pro license level (Basic, Standard, Advanced). No extension licenses are required; the extraction and the interpolation are computed internally, without Spatial Analyst. Esri's Extract Values to Points requires the Spatial Analyst extension at every license level.