DevTools Hub

Search tools

Search for a developer tool

URL Encoding in C#

Part of the Encoding Toolkit
Pattern
Uri.EscapeDataString(value)

the correct default for a single value like a query parameter — Uri.EscapeUriString, the old whole-URI escaper, is obsolete in modern .NET

Explanation

.NET has quietly deprecated its own whole-URI escaper, which makes the right default here narrower than in most languages: for a single value, reach for Uri.EscapeDataString and stop there.

Uri.EscapeDataString — the correct default

Escapes everything except RFC 2396/3986's unreserved characters (letters, digits, - _ . ~), converting a space to %20. Notably, that unreserved set is narrower than JavaScript's encodeURIComponent — C# also escapes ! * ' ( ), which JS deliberately leaves alone. Both outputs are valid percent-encoding; they just don't match byte-for-byte for the same input.

Uri.EscapeUriString — obsolete, don't use it

This used to be the whole-URI equivalent — leaving structural characters like /, ?, and : untouched while escaping the rest, the same role encodeURI plays in JavaScript. Modern .NET marks it [Obsolete] (diagnostic SYSLIB0013) with this exact warning: "Uri.EscapeUriString can corrupt the Uri string in some cases. Consider using Uri.EscapeDataString for query string components instead." There's no built-in replacement for escaping a full, already-assembled URI string at once — the supported path is to escape each component with EscapeDataString before assembling the URL, typically through UriBuilder, rather than escaping the whole thing in one call.

HttpUtility.UrlEncode / WebUtility.UrlEncode — form encoding, not URI encoding

Both encode a space as +, the application/x-www-form-urlencoded convention, not %20. HttpUtility lives in System.Web (ASP.NET-oriented); WebUtility lives in System.Net and needs no web-specific reference. Neither is a drop-in replacement for EscapeDataString — pick based on whether you're encoding a form/query value (either of these) or a general URI component (EscapeDataString), not by which namespace happens to already be imported.

For the underlying rules every one of these implements, see URL Encoding Explained. For the same component-vs-whole-URI split in JavaScript, see URL Encoding in JavaScript.

Valid examples

  • Uri.EscapeDataString("hello world") // "hello%20world"

    A single value — space escaped to %20, per RFC 2396/3986 percent-encoding.

  • Uri.EscapeDataString("a/b?c") // "a%2Fb%3Fc"

    / and ? both escaped — EscapeDataString treats them as literal data, not URI structure, correct for a value going into one component.

  • HttpUtility.UrlEncode("hello world") // "hello+world"

    Form-encoding convention — correct when building a value for application/x-www-form-urlencoded data, not a general URI component.

Invalid examples

  • Uri.EscapeUriString("q=hello world") // [Obsolete] SYSLIB0013

    Marked obsolete since .NET 6: "Uri.EscapeUriString can corrupt the Uri string in some cases." Use Uri.EscapeDataString per component instead.

  • $"https://api.example.com/search?q={userInput}"

    Raw string interpolation with no escaping at all — a userInput containing & or # silently corrupts the query string structure.

  • Uri.EscapeDataString("hello world") == HttpUtility.UrlEncode("hello world")

    false — EscapeDataString produces "hello%20world", HttpUtility.UrlEncode produces "hello+world". Both are valid encodings; they just don't match character-for-character.

Try it now