---
title: "Part-of-speech tagging in C#"
url: https://recursiveai.org/onenlp/cookbook/part-of-speech-tagging/
description: "Label English words as nouns, verbs and other parts of speech."
version: "1.0.0"
---

# Part-of-speech tagging in C#

**OneNLP** is a free, open-source natural language processing library for .NET from Recursive AI. MIT or Apache-2.0, no native dependencies.

[NuGet](https://www.nuget.org/packages/RecursiveAI.OneNlp.Models.English) · [GitHub](https://github.com/recursive-ai-oss/onenlp-csharp) · [Docs](https://recursiveai.org/onenlp/docs/) · [Download example (.zip)](https://recursiveai.org/onenlp/cookbook/part-of-speech-tagging/part-of-speech-tagging.zip)

Label English words as nouns, verbs and other parts of speech.

```shell
dotnet add package RecursiveAI.OneNlp.Models.English
```

Requires [.NET 10](https://dotnet.microsoft.com/download/dotnet/10.0) (net10.0); .NET 9 and earlier aren’t supported.

```csharp
using RecursiveAI.OneNlp;

Doc doc = Nlp.Analyze(
    "The cat sleeps.", Language.English);
foreach (Token token in doc)
    Console.WriteLine(
        $"{token.Text}: {token.Pos}");
```

```text
The: DET
cat: NOUN
sleeps: VERB
.: PUNCT
```

Unzip [the example](https://recursiveai.org/onenlp/cookbook/part-of-speech-tagging/part-of-speech-tagging.zip), then `dotnet run`.

## Full program

The program analyzes “The cat sleeps.” with the English model and prints each token’s universal part of speech. Punctuation is a token too. Passing `Language.English` explicitly avoids guessing the language of this short sentence.

The download’s `Program.cs` is the snippet above.

`dotnet run` prints:

```text
The: DET
cat: NOUN
sleeps: VERB
.: PUNCT
```

Without a language model, `Analyze` returns segmentation without the trained annotations; install the English model package, not just the core package.

## Variations

**Read language-specific tags and morphology.** A treebank is an annotated training dataset: its English tags `DT`, `NN` and `VBZ` are more specific than the universal categories `DET`, `NOUN` and `VERB`. `Tag` is the treebank’s tag; `Morph` holds features such as number and tense. This standalone variation analyzes the same sentence.

```csharp
using RecursiveAI.OneNlp;

Doc doc = Nlp.Analyze("The cat sleeps.", Language.English);
foreach (Token token in doc)
    Console.WriteLine($"{token.Text}: {token.Tag} {token.Morph}");
```

```text
The: DT Definite=Def|PronType=Art
cat: NN Number=Sing
sleeps: VBZ Mood=Ind|Number=Sing|Person=3|Tense=Pres|VerbForm=Fin
.: .
```

## Related recipes

- [Dependency parsing in C#](https://recursiveai.org/onenlp/cookbook/dependency-parsing/)
- [Generate sentence embeddings in C#](https://recursiveai.org/onenlp/cookbook/sentence-embeddings/)

## The short answer

For part-of-speech tagging in C#, install `RecursiveAI.OneNlp.Models.English`, call `Nlp.Analyze(text, Language.English)`, and read `Token.Pos`. The example labels “cat” as `NOUN` and “sleeps” as `VERB`. You get a structured document, not a string that you must split or parse again.

The model package is important. The core package can split text into words and sentences, but segmentation alone does not assign trained grammatical labels. The English package supplies the pipeline that produces the annotations shown here. See the [model package guide](https://recursiveai.org/onenlp/docs/model-packages/) for model selection and installation.

## How do I do part-of-speech tagging in C#?

Pass the original text to `Nlp.Analyze`. Keep the returned `Doc` while you inspect its tokens. Each `Token` exposes its text and annotations, so you can build a table, store results or select words by grammatical category without losing their connection to the document.

Choose the language explicitly when you already know it. Short fragments and names are not reliable inputs for language detection. A product that knows a document is English should not make language detection decide which pipeline to use for every fragment. If your input genuinely mixes languages, select the model for each independently processed text rather than assuming the English model handles everything.

The labels are model predictions. A successful call means analysis completed, not that every label is correct. Try the model on representative sentences from your own documents before turning a predicted tag into a business rule. An ambiguous word may have a different role in another sentence; tagging is contextual, not a dictionary lookup.

## What do the part-of-speech tags mean?

`Token.Pos` holds the universal category. In the example, `DET` is a determiner, `NOUN` a noun, `VERB` a verb and `PUNCT` punctuation. Use this field when your application needs broad categories rather than a particular treebank’s notation.

`Token.Tag` holds the treebank-specific tag. Here, `DT`, `NN` and `VBZ` describe the English tokens in more detail. `Token.Morph` is a separate field: “sleeps” includes present tense and third-person singular features. The variation above prints both fields so you can see their actual representation rather than assuming a tag contains all morphology.

A missing tag is not always an installation error. The [fast-tier documentation](https://recursiveai.org/onenlp/docs/fast-tier/) says treebanks without an XPOS column have no tagger, leaving `Token.Tag` empty. Universal POS and language-specific tags are different annotations. Check the language package’s documented fields before requiring every field to be nonempty.

## Where can I find a C# part-of-speech tagging example?

The download contains the complete project, the exact package references and the sentence in `Program.cs`. It does not require an API key or a separate model download at runtime. Restore the packages, run the program and compare its output with the lines above.

For larger inputs, preserve sentence context instead of tagging each word in isolation. The [API contracts](https://recursiveai.org/onenlp/docs/contracts/) describe annotations, and the [fast-tier guide](https://recursiveai.org/onenlp/docs/fast-tier/) explains which components produce them. If you need relations between words rather than their categories, use the dependency fields in the same analyzed document.
