---
name: r.stream.extract
description: Performs stream network extraction.
keywords: [ raster, hydrology, stream network ]
---

# r.stream.extract

Performs stream network extraction.

=== "Command line"

    **r.stream.extract**
    **elevation**=*name*
    [**accumulation**=*name*]
    [**depression**=*name*]
    **threshold**=*float*
    [**d8cut**=*float*]
    [**mexp**=*float*]
    [**stream_length**=*integer*]
    [**memory**=*memory in MB*]
    [**stream_raster**=*name*]
    [**stream_vector**=*name*]
    [**direction**=*name*]
    [**--overwrite**]
    [**--verbose**]
    [**--quiet**]
    [**--qq**]
    [**--ui**]

    Example:

    ```sh
    r.stream.extract elevation=name threshold=0.0
    ```

=== "Python (grass.tools)"

    *grass.tools.Tools.r_stream_extract*(**elevation**,
        **accumulation**=*None*,
        **depression**=*None*,
        **threshold**,
        **d8cut**=*None*,
        **mexp**=*0*,
        **stream_length**=*0*,
        **memory**=*300*,
        **stream_raster**=*None*,
        **stream_vector**=*None*,
        **direction**=*None*,
        **overwrite**=*None*,
        **verbose**=*None*,
        **quiet**=*None*,
        **superquiet**=*None*)

    Example:

    ```python
    tools = Tools()
    tools.r_stream_extract(elevation="name", threshold=0.0)
    ```

    This grass.tools API is experimental in version 8.5 and expected to be stable in version 8.6.

=== "Python (grass.script)"

    *grass.script.run_command*("***r.stream.extract***",
        **elevation**,
        **accumulation**=*None*,
        **depression**=*None*,
        **threshold**,
        **d8cut**=*None*,
        **mexp**=*0*,
        **stream_length**=*0*,
        **memory**=*300*,
        **stream_raster**=*None*,
        **stream_vector**=*None*,
        **direction**=*None*,
        **overwrite**=*None*,
        **verbose**=*None*,
        **quiet**=*None*,
        **superquiet**=*None*)

    Example:

    ```python
    gs.run_command("r.stream.extract", elevation="name", threshold=0.0)
    ```

## Parameters

=== "Command line"

    **elevation**=*name* **[required]**  
    &nbsp;&nbsp;&nbsp;&nbsp;Name of input elevation raster map  
    **accumulation**=*name*  
    &nbsp;&nbsp;&nbsp;&nbsp;Name of input accumulation raster map  
    &nbsp;&nbsp;&nbsp;&nbsp;Stream extraction will use provided accumulation instead of calculating it anew  
    **depression**=*name*  
    &nbsp;&nbsp;&nbsp;&nbsp;Name of input raster map with real depressions  
    &nbsp;&nbsp;&nbsp;&nbsp;Streams will not be routed out of real depressions  
    **threshold**=*float* **[required]**  
    &nbsp;&nbsp;&nbsp;&nbsp;Minimum flow accumulation for streams  
    &nbsp;&nbsp;&nbsp;&nbsp;Must be &gt; 0  
    **d8cut**=*float*  
    &nbsp;&nbsp;&nbsp;&nbsp;Use SFD above this threshold  
    &nbsp;&nbsp;&nbsp;&nbsp;If accumulation is larger than d8cut, SFD is used instead of MFD. Applies only if no accumulation map is given.  
    **mexp**=*float*  
    &nbsp;&nbsp;&nbsp;&nbsp;Montgomery exponent for slope, disabled with 0  
    &nbsp;&nbsp;&nbsp;&nbsp;Montgomery: accumulation is multiplied with pow(slope,mexp) and then compared with threshold  
    &nbsp;&nbsp;&nbsp;&nbsp;Default: *0*  
    **stream_length**=*integer*  
    &nbsp;&nbsp;&nbsp;&nbsp;Delete stream segments shorter than stream_length cells  
    &nbsp;&nbsp;&nbsp;&nbsp;Applies only to first-order stream segments (springs/stream heads)  
    &nbsp;&nbsp;&nbsp;&nbsp;Default: *0*  
    **memory**=*memory in MB*  
    &nbsp;&nbsp;&nbsp;&nbsp;Maximum memory to be used (in MB)  
    &nbsp;&nbsp;&nbsp;&nbsp;Cache size for raster rows  
    &nbsp;&nbsp;&nbsp;&nbsp;Default: *300*  
    **stream_raster**=*name*  
    &nbsp;&nbsp;&nbsp;&nbsp;Name for output raster map with unique stream ids  
    **stream_vector**=*name*  
    &nbsp;&nbsp;&nbsp;&nbsp;Name for output vector map with unique stream ids  
    **direction**=*name*  
    &nbsp;&nbsp;&nbsp;&nbsp;Name for output raster map with flow direction  
    **--overwrite**  
    &nbsp;&nbsp;&nbsp;&nbsp;Allow output files to overwrite existing files  
    **--help**  
    &nbsp;&nbsp;&nbsp;&nbsp;Print usage summary  
    **--verbose**  
    &nbsp;&nbsp;&nbsp;&nbsp;Verbose module output  
    **--quiet**  
    &nbsp;&nbsp;&nbsp;&nbsp;Quiet module output  
    **--qq**  
    &nbsp;&nbsp;&nbsp;&nbsp;Very quiet module output  
    **--ui**  
    &nbsp;&nbsp;&nbsp;&nbsp;Force launching GUI dialog

=== "Python (grass.tools)"

    **elevation** : str | np.ndarray, *required*  
    &nbsp;&nbsp;&nbsp;&nbsp;Name of input elevation raster map  
    &nbsp;&nbsp;&nbsp;&nbsp;Used as: input, raster, *name*  
    **accumulation** : str | np.ndarray, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Name of input accumulation raster map  
    &nbsp;&nbsp;&nbsp;&nbsp;Stream extraction will use provided accumulation instead of calculating it anew  
    &nbsp;&nbsp;&nbsp;&nbsp;Used as: input, raster, *name*  
    **depression** : str | np.ndarray, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Name of input raster map with real depressions  
    &nbsp;&nbsp;&nbsp;&nbsp;Streams will not be routed out of real depressions  
    &nbsp;&nbsp;&nbsp;&nbsp;Used as: input, raster, *name*  
    **threshold** : float, *required*  
    &nbsp;&nbsp;&nbsp;&nbsp;Minimum flow accumulation for streams  
    &nbsp;&nbsp;&nbsp;&nbsp;Must be &gt; 0  
    **d8cut** : float, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Use SFD above this threshold  
    &nbsp;&nbsp;&nbsp;&nbsp;If accumulation is larger than d8cut, SFD is used instead of MFD. Applies only if no accumulation map is given.  
    **mexp** : float, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Montgomery exponent for slope, disabled with 0  
    &nbsp;&nbsp;&nbsp;&nbsp;Montgomery: accumulation is multiplied with pow(slope,mexp) and then compared with threshold  
    &nbsp;&nbsp;&nbsp;&nbsp;Default: *0*  
    **stream_length** : int, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Delete stream segments shorter than stream_length cells  
    &nbsp;&nbsp;&nbsp;&nbsp;Applies only to first-order stream segments (springs/stream heads)  
    &nbsp;&nbsp;&nbsp;&nbsp;Default: *0*  
    **memory** : int, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Maximum memory to be used (in MB)  
    &nbsp;&nbsp;&nbsp;&nbsp;Cache size for raster rows  
    &nbsp;&nbsp;&nbsp;&nbsp;Used as: *memory in MB*  
    &nbsp;&nbsp;&nbsp;&nbsp;Default: *300*  
    **stream_raster** : str | type(np.ndarray) | type(np.array) | type(gs.array.array), *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Name for output raster map with unique stream ids  
    &nbsp;&nbsp;&nbsp;&nbsp;Used as: output, raster, *name*  
    **stream_vector** : str, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Name for output vector map with unique stream ids  
    &nbsp;&nbsp;&nbsp;&nbsp;Used as: output, vector, *name*  
    **direction** : str | type(np.ndarray) | type(np.array) | type(gs.array.array), *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Name for output raster map with flow direction  
    &nbsp;&nbsp;&nbsp;&nbsp;Used as: output, raster, *name*  
    **overwrite** : bool, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Allow output files to overwrite existing files  
    &nbsp;&nbsp;&nbsp;&nbsp;Default: *None*  
    **verbose** : bool, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Verbose module output  
    &nbsp;&nbsp;&nbsp;&nbsp;Default: *None*  
    **quiet** : bool, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Quiet module output  
    &nbsp;&nbsp;&nbsp;&nbsp;Default: *None*  
    **superquiet** : bool, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Very quiet module output  
    &nbsp;&nbsp;&nbsp;&nbsp;Default: *None*  

    Returns:

    **result** : grass.tools.support.ToolResult | np.ndarray | tuple[np.ndarray] | None  
    If the tool produces text as standard output, a *ToolResult* object will be returned. Otherwise, `None` will be returned. If an array type (e.g., *np.ndarray*) is used for one of the raster outputs, the result will be an array and will have the shape corresponding to the computational region. If an array type is used for more than one raster output, the result will be a tuple of arrays.

    Raises:

    *grass.tools.ToolError*: When the tool ended with an error.

=== "Python (grass.script)"

    **elevation** : str, *required*  
    &nbsp;&nbsp;&nbsp;&nbsp;Name of input elevation raster map  
    &nbsp;&nbsp;&nbsp;&nbsp;Used as: input, raster, *name*  
    **accumulation** : str, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Name of input accumulation raster map  
    &nbsp;&nbsp;&nbsp;&nbsp;Stream extraction will use provided accumulation instead of calculating it anew  
    &nbsp;&nbsp;&nbsp;&nbsp;Used as: input, raster, *name*  
    **depression** : str, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Name of input raster map with real depressions  
    &nbsp;&nbsp;&nbsp;&nbsp;Streams will not be routed out of real depressions  
    &nbsp;&nbsp;&nbsp;&nbsp;Used as: input, raster, *name*  
    **threshold** : float, *required*  
    &nbsp;&nbsp;&nbsp;&nbsp;Minimum flow accumulation for streams  
    &nbsp;&nbsp;&nbsp;&nbsp;Must be &gt; 0  
    **d8cut** : float, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Use SFD above this threshold  
    &nbsp;&nbsp;&nbsp;&nbsp;If accumulation is larger than d8cut, SFD is used instead of MFD. Applies only if no accumulation map is given.  
    **mexp** : float, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Montgomery exponent for slope, disabled with 0  
    &nbsp;&nbsp;&nbsp;&nbsp;Montgomery: accumulation is multiplied with pow(slope,mexp) and then compared with threshold  
    &nbsp;&nbsp;&nbsp;&nbsp;Default: *0*  
    **stream_length** : int, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Delete stream segments shorter than stream_length cells  
    &nbsp;&nbsp;&nbsp;&nbsp;Applies only to first-order stream segments (springs/stream heads)  
    &nbsp;&nbsp;&nbsp;&nbsp;Default: *0*  
    **memory** : int, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Maximum memory to be used (in MB)  
    &nbsp;&nbsp;&nbsp;&nbsp;Cache size for raster rows  
    &nbsp;&nbsp;&nbsp;&nbsp;Used as: *memory in MB*  
    &nbsp;&nbsp;&nbsp;&nbsp;Default: *300*  
    **stream_raster** : str, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Name for output raster map with unique stream ids  
    &nbsp;&nbsp;&nbsp;&nbsp;Used as: output, raster, *name*  
    **stream_vector** : str, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Name for output vector map with unique stream ids  
    &nbsp;&nbsp;&nbsp;&nbsp;Used as: output, vector, *name*  
    **direction** : str, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Name for output raster map with flow direction  
    &nbsp;&nbsp;&nbsp;&nbsp;Used as: output, raster, *name*  
    **overwrite** : bool, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Allow output files to overwrite existing files  
    &nbsp;&nbsp;&nbsp;&nbsp;Default: *None*  
    **verbose** : bool, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Verbose module output  
    &nbsp;&nbsp;&nbsp;&nbsp;Default: *None*  
    **quiet** : bool, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Quiet module output  
    &nbsp;&nbsp;&nbsp;&nbsp;Default: *None*  
    **superquiet** : bool, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Very quiet module output  
    &nbsp;&nbsp;&nbsp;&nbsp;Default: *None*

## DESCRIPTION

*r.stream.extract* extracts streams in both raster and vector format
from a required input **elevation** map and optional input
**accumulation** map.

## NOTES

NULL (nodata) cells in the input **elevation** map are ignored, zero and
negative values are valid elevation data. Gaps in the elevation map that
are located within the area of interest must be filled beforehand, e.g.
with *[r.fillnulls](r.fillnulls.md)*, to avoid distortions.

All non-NULL and non-zero cells of **depression** map will be regarded
as real depressions. Streams will not be routed out of depressions. If
an area is marked as depression but the elevation model has no
depression at this location, streams will not stop there. If a flow
accumulation map and a map with real depressions are provided, the flow
accumulation map must match the depression map such that flow is not
distributed out of the indicated depressions. It is recommended to use
internally computed flow accumulation if a depression map is provided.

Option **threshold** defines the minimum (optionally modified) flow
accumulation value that will initiate a new stream. If Montgomery's
method for channel initiation is used, the cell value of the
accumulation input map is multiplied by
`(tan(local slope))^mexp` and then compared to
**threshold**. If **mexp** is given, then the method of Montgomery and
Foufoula-Georgiou (1993) is used to initiate a stream with this value.
The cell value of the accumulation input map is multiplied by
`(tan(local slope))^mexp` and then compared to
**threshold**. If threshold is reached or exceeded, a new stream is
initiated. The default value 0 disables Montgomery. Montgomery and
Foufoula-Georgiou (1993) generally recommend to use 2.0 as exponent.
**mexp** values closer to 0 will produce streams more similar to streams
extracted with Montgomery disabled. Larger **mexp** values decrease the
number of streams in flat areas and increase the number of streams in
steep areas. If **weight** is given, the weight is applied first.

Option **d8cut** defines minimum amount of overland flow (accumulation)
when SFD (D8) will be used instead of MFD (FD8) to calculate flow
accumulation. Only applies if no accumulation map is provided. Setting
to 0 disables MFD completely.

Option **stream_length** defines minimum stream length in number of
cells for first-order (head/spring) stream segments. All first-order
stream segments shorter than **stream_length** will be deleted.

Output **direction** raster map contains flow direction for all non-NULL
cells in input elevation. Flow direction is of D8 type with a range of 1
to 8. Multiplying values with 45 gives degrees CCW from East. Flow
direction was adjusted during thinning, taking shortcuts and skipping
cells that were eliminated by the thinning procedure.

### Stream extraction

If no **accumulation** input map is provided, flow accumulation is
determined with a hydrological analysis similar to
*[r.watershed](r.watershed.md)*. The algorithm is MFD (FD8) after
Holmgren 1994, as for *[r.watershed](r.watershed.md)*. The **threshold**
option determines the number of streams and detail of stream networks.
Whenever flow accumulation reaches **threshold**, a new stream is
started and traced downstream to its outlet point. As for
*[r.watershed](r.watershed.md)*, flow accumulation is calculated as the
number of cells draining through a cell.

If **accumulation** is given, then the accumulation values of the
provided **accumulation** map are used and not calculated from the input
**elevation** map. In this case, the **elevation** map must be exactly
the same map used to calculate **accumulation**. If **accumulation** was
calculated with *[r.terraflow](r.terraflow.md)*, the filled elevation
output of *[r.terraflow](r.terraflow.md)* must be used. Further on, the
current region should be aligned to the **accumulation** map. Flow
direction is first calculated from **elevation** and then adjusted to
**accumulation**. It is not necessary to provide **accumulation** as the
number of cells, it can also be the optionally adjusted or weighed total
contributing area in square meters or any other unit. When an original
flow accumulation map is adjusted or weighed, the adjustment or weighing
should not convert valid accumulation values to NULL (nodata) values.

In case of getting the error message
`ERROR: Accumulation raster map is NULL but elevation map is not NULL`
the computational region must be carefully adjusted to exclude NULL
pixels in the accumulation raster map prior to stream extraction.

### Weighed flow accumulation

Flow accumulation can be calculated first, e.g. with
*[r.watershed](r.watershed.md)*, and then modified before using it as
input for *r.stream.extract*. In its general form, a weighed
accumulation map is generated by first creating a weighing map and then
multiplying the accumulation map with the weighing map using
*[r.mapcalc](r.mapcalc.md)*. It is highly recommended to evaluate the
weighed flow accumulation map first, before using it as input for
*r.stream.extract*.

This allows e.g. to decrease the number of streams in dry areas and
increase the number of streams in wet areas by setting **weight** to
smaller than 1 in dry areas and larger than 1 in wet areas.

Another possibility is to restrict channel initiation to valleys
determined from terrain morphology. Valleys can be determined with
*[r.param.scale](r.param.scale.md)* `method=crosc` (cross-sectional or
tangential curvature). Curvature values \< 0 indicate concave features,
i.e. valleys. The size of the processing window determines whether
narrow or broad valleys will be identified (See example below).

### Defining a region of interest

The stream extraction procedure can be restricted to a certain region of
interest, e.g. a subbasin, by setting the computational region with
*[g.region](g.region.md)* and/or creating a mask with
*[r.mask](r.mask.md)*. Such region of interest should be a complete
catchment area, complete in the sense that the complete area upstream of
an outlet point is included and buffered with at least one cell.

### Stream output

The output raster and vector contains stream segments with unique IDs.
Note that these IDs are different from the IDs assigned by
*[r.watershed](r.watershed.md)*. The vector output also contains points
at the location of the start of a stream segment, at confluences and at
stream network outlet locations.

Output **stream_raster** raster map stores extracted streams. Cell
values encode a unique ID for each stream segment.

Output **stream_vector** vector map stores extracted stream segments and
points. Points are written at the start location of each stream segment
and at the outlet of a stream network. In layer 1, categories are unique
IDs, identical to the cell value of the raster output. The attribute
table for layer 1 holds information about the type of stream segment:
start segment, or intermediate segment with tributaries, and about the
stream network this stream or node belongs to. Columns are
`cat int,stream_type varchar(),type_code int,network int`. The network
attribute is the network ID of the stream/node. The encoding for
type_code is 0 = start, 1 = intermediate. In layer 2, categories are
identical to type_code in layer 1 with additional category 2 = outlet
for outlet points. Points with category 1 = intermediate in layer 2 are
at the location of confluences.

## EXAMPLE

This example is based on the elevation map "elev_ned_30m" in the North
Carolina sample dataset and uses valleys determined with
*[r.param.scale](r.param.scale.md)* to weigh an accumulation map
produced with *[r.watershed](r.watershed.md)*.

```sh
# set region
g.region -p raster=elev_ned_30m@PERMANENT

# calculate flow accumulation
r.watershed ele=elev_ned_30m@PERMANENT acc=elev_ned_30m.acc

# curvature to get narrow valleys
r.param.scale input=elev_ned_30m@PERMANENT output=tangential_curv_5 size=5 method=crosc

# curvature to get a bit broader valleys
r.param.scale input=elev_ned_30m@PERMANENT output=tangential_curv_7 size=7 method=crosc

# curvature to get broad valleys
r.param.scale input=elev_ned_30m@PERMANENT output=tangential_curv_11 size=11 method=crosc

# create weight map
r.mapcalc "weight = if(tangential_curv_5 < 0, -100 * tangential_curv_5, \
                    if(tangential_curv_7 < 0, -100 * tangential_curv_7, \
                    if(tangential_curv_11 < 0, -100 * tangential_curv_11, 0.000001)))"

# weigh accumulation map
r.mapcalc expr="elev_ned_30m.acc.weighed = elev_ned_30m.acc * weight"

# copy color table from original accumulation map
r.colors map=elev_ned_30m.acc.weighed raster=elev_ned_30m.acc
```

![Weight map](r_stream_extract_weights_zoom.png)  
*Weight map (spatial subset with lake in the southern half)*

![Original flow accumulation map](r_stream_extract_accum_orig_zoom.png)  
*Original flow accumulation map (spatial subset with lake in the southern
half)*

![Weighed flow accumulation map](r_stream_extract_accum_weighted_zoom.png)  
*Weighed flow accumulation map (spatial subset with lake in the southern
half)*

Display both the original and the weighed accumulation map. Compare them
and proceed if the weighed accumulation map makes sense.

```sh
# extract streams using the original accumulation map
r.stream.extract elevation=elev_ned_30m@PERMANENT \
                 accumulation=elev_ned_30m.acc \
                 threshold=1000 \
                 stream_rast=elev_ned_30m.streams.noweight

# extract streams from weighed map
# note that the weighed map is a bit smaller than the original map

r.stream.extract elevation=elev_ned_30m@PERMANENT \
                 accumulation=elev_ned_30m.acc.weighed \
                 threshold=1000 \
                 stream_rast=elev_ned_30m.streams
```

Now display both stream maps and decide which one is more realistic.

![Extracted streams from original flow accumulation map](r_stream_extract_streams_noweight.png)  
*Extracted streams from original flow accumulation map*

![Extracted streams from weighed flow accumulation map](r_stream_extract_streams_weighed.png)  
*Extracted streams from weighed flow accumulation map*

## REFERENCES

- Ehlschlaeger, C. (1989). *Using the A^T Search Algorithm to
  Develop Hydrologic Models from Digital Elevation Data*, **Proceedings
  of International Geographic Information Systems (IGIS) Symposium
  '89**, pp 275-281 (Baltimore, MD, 18-19 March 1989). URL:
  <https://www.researchgate.net/publication/243781937_Using_the_AT_search_algorithm_to_develop_hydrologic_models_from_digital_elevation_data>
- Holmgren, P. (1994). *Multiple flow direction algorithms for runoff
  modelling in grid based elevation models: An empirical evaluation.*
  **Hydrological Processes** Vol 8(4), pp 327-334. DOI:
  [10.1002/hyp.3360080405](https://doi.org/10.1002/hyp.3360080405)
- Montgomery, D.R., Foufoula-Georgiou, E. (1993). *Channel network
  source representation using digital elevation models.* **Water
  Resources Research** Vol 29(12), pp 3925-3934.

## SEE ALSO

*[r.mapcalc](r.mapcalc.md), [r.param.scale](r.param.scale.md),
[r.stream.channel](https://grass.osgeo.org/grass8/manuals/addons/r.stream.channel.html)
(Addon),
[r.stream.distance](https://grass.osgeo.org/grass8/manuals/addons/r.stream.distance.html)
(Addon),
[r.stream.order](https://grass.osgeo.org/grass8/manuals/addons/r.stream.order.html)
(Addon),
[r.stream.segment](https://grass.osgeo.org/grass8/manuals/addons/r.stream.segment.html)
(Addon),
[r.stream.slope](https://grass.osgeo.org/grass8/manuals/addons/r.stream.slope.html)
(Addon),
[r.stream.snap](https://grass.osgeo.org/grass8/manuals/addons/r.stream.snap.html)
(Addon),
[r.stream.stats](https://grass.osgeo.org/grass8/manuals/addons/r.stream.stats.html)
(Addon), [r.terraflow](r.terraflow.md), [r.thin](r.thin.md),
[r.to.vect](r.to.vect.md), [r.watershed](r.watershed.md)*

See also [r.streams.\*
modules](https://grasswiki.osgeo.org/wiki/R.stream.*_modules) wiki page.

## AUTHOR

Markus Metz

## SOURCE CODE

Available at: [r.stream.extract source code](https://github.com/OSGeo/grass/tree/main/raster/r.stream.extract)
([history](https://github.com/OSGeo/grass/commits/main/raster/r.stream.extract))  
Latest change: Friday Apr 17 01:04:26 2026 in commit [32a1433](https://github.com/OSGeo/grass/commit/32a143358df26b2e518b03c7e0d79541e8d1e5b1)
