Blog

RDP vs. VNC: What's the Difference Between the Two Most Popular Remote Desktop Protocols?

RDP and VNC both let you remotely connect to your computer, but they solve the problem in very different ways. Learn how each protocol works, where they came from, and when to pick one over the other.

October 17, 2026 Aaron Crawfis 21 min read

If you search for “RDP vs. VNC”, you’ll usually get the basics again and again: RDP is from Microsoft and is faster, VNC is open and works everywhere. While that’s true, you might want to learn more about RDP and VNC. How do they work? What do the protocols include? Why has RDP been hard to use outside of Windows, like on macOS? The reasons come down to how each protocol was designed, what problem its authors were trying to solve, and how much each one has changed over the last 25 years.

This post walks through both the RDP and VNC protocols, even down to the wire level. We’ll look at how a connection gets set up, how pixels get from one machine to another, how keyboard and mouse input travels back, and how each protocol handles everything else like audio, clipboard, and security. Along the way there’s a bit of history, because a lot of the differences make more sense once you know where each protocol started.

The TL;DR of RDP and VNC

Both the RDP and VNC protocols let you see and control a computer over a network, from another computer. The big difference is the level they work at.

VNC works at the pixel level. The server looks at its screen, figures out which rectangles of pixels changed, and sends those rectangles to the client. The client then draws them. That’s essentially the whole model. It doesn’t know or care what a window, a font, or a video is.

RDP works at a higher level. It started out sending drawing commands (“draw this text here, fill this rectangle with blue”) instead of finished pixels, and it was built from day one as a framework of channels that carry graphics, input, audio, clipboard, printers, drives, and more over one connection. While modern RDP replaces most of the drawing commands with video codecs like H.264, the multi-channel design is still at the core of it.

Let’s dive into a little history and then explore how each protocol works in detail.

A bit of history on RDP and VNC

VNC: a research project from Cambridge

VNC stands for Virtual Network Computing. It came out of the Olivetti & Oracle Research Laboratory (ORL) in Cambridge, England, in the late 1990s. The team there had been working on thin clients, and they wanted a way for any lightweight device to display a desktop running somewhere else. Their answer was a protocol called RFB, short for Remote Framebuffer.

A framebuffer is just the block of memory that holds the pixels currently on screen. The idea behind RFB was intentionally simple: if a client can receive updates to a framebuffer and send back key presses and mouse movements, it can control any graphical system, regardless of the operating system or windowing toolkit underneath.

ORL released VNC as open source in 1998. AT&T bought the lab in 1999, then closed it in 2002, and several of the original developers went on to found RealVNC. Because the code and protocol were open, lots of forks appeared over the years: TightVNC, UltraVNC, TigerVNC, LibVNCServer, and others. Each added its own extensions which added new features like better compression, encryption, and file transfer, but not all clients and servers support all extensions. The core protocol was eventually written up as RFC 6143 in 2011, which documents RFB version 3.8.

Fast-forward to today: the base protocol is small, well documented, and easy to implement, but most of the features people actually want (better compression, encryption, file transfer) live in extensions that vary from one implementation to the next. So when you choose a VNC client or server, you need to be aware of which extensions it provides, which operating systems it supports, and whether it will interoperate with the other side.

If you’ve ever turned on macOS Screen Sharing and tried to connect using a VNC client, you know the pain of dealing with compatibility issues firsthand.

RDP: Microsoft’s answer to terminal servers

RDP stands for Remote Desktop Protocol. Microsoft introduced it in 1998 with Windows NT 4.0 Terminal Server Edition. The goal was different from VNC’s. Microsoft wanted many users to run their own sessions on one shared Windows server, each from a cheap terminal or an older PC, so bandwidth and server efficiency mattered a lot. Many of those connections were going over slow WAN links or even dial-up modems.

RDP wasn’t designed from scratch. It’s built on top of the ITU T.120 family of standards, which were created for multipoint conferencing and application sharing. In particular, RDP borrowed T.125, the Multipoint Communication Service (MCS), which gives it the idea of multiple named channels inside a single connection. That decision from 1998 is why RDP can carry so many different kinds of data today.

Since then, RDP evolved with almost every Windows release:

  • Windows 2000 and XP (RDP 5.x): Remote Desktop became a built-in feature for regular users, not just terminal servers. Printer, drive, and audio redirection showed up.
  • Windows Vista (RDP 6.0): Network Level Authentication (NLA) arrived, which authenticates the user before the server spends resources on a session.
  • Windows 7 SP1 (RDP 7.1): RemoteFX added a codec for rich graphics and GPU acceleration on the server.
  • Windows 8 and 8.1 (RDP 8.x): UDP transport and a new graphics pipeline, including H.264 video encoding.
  • Windows 10 and later (RDP 10.x): Better H.264 modes with full color quality, plus improvements for high-DPI displays and multiple monitors.

Around 2008, following European antitrust rulings, Microsoft started publishing detailed specifications for its protocols through its Open Specifications program. RDP is documented across dozens of documents, starting with MS-RDPBCGR (Basic Connectivity and Graphics Remoting). That’s what makes third-party RDP clients and servers like FreeRDP, xrdp, and ProRDP possible.

How VNC works

How the VNC connection handshake works

To kick things off, the client and server first exchange version information to agree on the RFB protocol version they will use. An RFB connection usually runs over TCP port 5900 (or 5900 plus a display number, so display :1 is port 5901). The handshake is pretty straightforward:

  1. Version exchange. The server sends a 12-byte string announcing the highest version it supports, like RFB 003.008\n. The client replies with the version it wants to use.
  2. Security negotiation. The server sends a list of security types it supports. The client picks one. The base spec only defines two: None and VNC Authentication.
  3. Authentication. For VNC Authentication, the server sends a random 16-byte challenge. The client encrypts it with DES, using the password as the key, and sends it back. The server checks the result.
  4. Initialization. The client sends a ClientInit message saying whether it’s OK to share the session with other viewers. The server answers with ServerInit, which contains the framebuffer width and height, its pixel format, and a name for the desktop.
Client                                    Server
  |  <---------- "RFB 003.008\n"  -----------  |
  |  ----------  "RFB 003.008\n"  ---------->  |
  |  <---------- security types [1, 2] ------  |
  |  ----------  chosen type: 2  ----------->  |
  |  <---------- 16-byte challenge ----------  |
  |  ----------  DES(challenge, pw) -------->  |
  |  <---------- SecurityResult: OK ---------  |
  |  ----------  ClientInit (shared=1) ----->  |
  |  <---------- ServerInit (w, h, fmt) -----  |

After that, the session is just a stream of messages in both directions.

The VNC message types

The core protocol has only six message types from client to server and four from server to client.

DirectionMessageWhat it does
Client to serverSetPixelFormatTells the server how to encode pixels (bits per pixel, color layout)
Client to serverSetEncodingsLists the compression encodings the client understands, in order of preference (e.g., raw, copyrect, hextile)
Client to serverFramebufferUpdateRequestAsks for an update to a region of the screen (x, y, width, height)
Client to serverKeyEventA key was pressed or released (key code and state)
Client to serverPointerEventThe mouse moved or a button changed (x, y, button mask)
Client to serverClientCutTextClipboard text from the client (Latin-1 text)
Server to clientFramebufferUpdateOne or more rectangles of new pixel data (x, y, width, height, encoding)
Server to clientSetColourMapEntriesPalette data for old 8-bit color modes (first color, number of colors, color values)
Server to clientBellRing the bell
Server to clientServerCutTextClipboard text from the server (Latin-1 text)

That small surface area is a big part of why VNC is everywhere. It’s easy to implement, and you can add a VNC server to almost anything that has a framebuffer, including embedded devices, virtual machine hypervisors, and headless Linux boxes.

How VNC pixels are transmitted

The most important thing to understand about RFB is that it’s client-driven. The server doesn’t stream updates on its own. The client sends a FramebufferUpdateRequest, and the server replies with a FramebufferUpdate covering whatever changed. If nothing changed, the server can hold the request until something does.

Most clients send a new request as soon as each update arrives. That works fine on a local network, but it means you get at most one screen update per network round trip. On a connection with 50 ms of latency, that puts a ceiling of about 20 updates per second on the session before you even think about bandwidth or encoding time. Some implementations add a “continuous updates” extension to let the server push freely, but support varies between clients and servers.

Each rectangle in an update is tagged with an encoding, which describes how its pixels are compressed. The client tells the server which encodings it supports with SetEncodings, and the server picks from that list. The common ones are:

  • Raw: uncompressed pixels, left to right, top to bottom. Simple and huge.
  • CopyRect: “copy this rectangle from somewhere else on the screen.” Very cheap, and great for scrolling or dragging a window, when the server can detect it.
  • RRE and Hextile: early schemes that describe a rectangle as a background color plus smaller solid-colored sub-rectangles. Good for flat UIs from the 1990s, not so much for photos or gradients.
  • ZRLE and TRLE: tile-based run-length and palette encoding, with zlib compression on top in ZRLE’s case. A good general-purpose choice.
  • Tight: an extension from the TightVNC project that picks between zlib and JPEG per rectangle. JPEG makes photos and video much smaller, at the cost of visible compression artifacts.

There are also pseudo-encodings, which use the same mechanism to signal features rather than send pixels. The two you’ll see most are the Cursor pseudo-encoding, which lets the client draw the mouse cursor locally instead of waiting for the server, and DesktopSize, which tells the client the remote screen resolution changed.

Each of the above encodings describes pixels that already exist on the server’s screen. The server has to capture the screen, compare it against what it sent before to find changed regions, compress those regions, and send them. When large parts of the screen change constantly, like during video playback or while dragging a window, that pipeline gets expensive in both CPU and bandwidth. That explains the stuttering, lag, and high resource usage you often experience with VNC.

How VNC user input is handled

Input in RFB is pretty simple. A KeyEvent carries a down/up flag and an X11 keysym, which is a number identifying the symbol on the key (like a, Shift_L, or F5). A PointerEvent carries an x and y position and a bitmask of up to eight buttons. The scroll wheel is represented as buttons 4 and 5 being pressed and released.

Using keysyms instead of physical key codes means the client sends the character the user meant, not the key they pressed. This causes problems with non-US keyboard layouts, dead keys, and modifier combinations, because the server has to reverse-engineer which physical keys would produce that symbol on its own layout. Several VNC implementations have added extensions to send raw scan codes instead for this reason.

How a VNC connection is secured

The base RFB protocol does not encrypt anything after authentication. Your screen contents and every key you type, including passwords typed into the remote machine, travel in the clear. VNC Authentication itself is also weak by modern standards. It uses DES, and passwords are truncated to 8 characters.

Different VNC projects have filled this gap in different ways. VeNCrypt wraps the session in TLS. RealVNC has its own encrypted security types. Apple’s Screen Sharing uses its own authentication scheme, which provides encryption and authentication integrated with macOS. The standard advice for years has been to tunnel VNC over SSH or a VPN, which works, but it means security depends on how carefully each user sets it up.

What VNC doesn’t do

Because RFB focuses on the framebuffer, a lot of things are out of scope for the core protocol:

  • No audio. There’s nothing in the spec for sound.
  • Basic clipboard. ClientCutText and ServerCutText carry Latin-1 text only. An extended clipboard extension adds Unicode and other formats, but it isn’t universal among VNC implementations.
  • No file transfer, printer, or drive redirection in the base protocol. Several implementations add their own.
  • Fixed resolution. The client sees the server’s screen at the server’s resolution. If you connect from a laptop to a machine with a 5K display, you either scale it down or scroll around.

If you’ve ever used a VNC client to connect to your Mac, you’ve probably noticed that the screen resolution doesn’t automatically adjust to your client window size, and that you can’t transfer files either. It’s because VNC wasn’t built with these features in mind.

How RDP works

The RDP layered stack

RDP is more complex, and the best way to understand it is as a set of layers. The default port is TCP 3389 (and UDP 3389 for the newer transport). From the bottom up, a classic RDP connection looks like this:

+--------------------------------------------------+
|  RDP PDUs (graphics, input, capabilities, etc.)  |
|  Virtual channels (clipboard, audio, drives)     |
+--------------------------------------------------+
|  MCS  (T.125: multiple channels in one link)     |
+--------------------------------------------------+
|  X.224 (connection setup, negotiation)           |
+--------------------------------------------------+
|  TPKT  (RFC 1006: framing over TCP)              |
+--------------------------------------------------+
|  TLS                                             |
+--------------------------------------------------+
|  TCP                                             |
+--------------------------------------------------+

The T.120 heritage shows up in the middle two layers. X.224 and MCS were designed for telecom-style conferencing, which is why the RDP spec talks about things like “domains”, “users”, and “channel joins”. Once you get past the terminology, the important part is that MCS lets one TCP connection carry many independent channels, each with its own ID.

For the most common traffic, RDP also has a fast-path format that skips most of those headers. Keyboard and mouse input and most screen updates use fast-path, so the layering doesn’t add much overhead in practice.

The RDP connection sequence

Setting up an RDP connection involves more steps than VNC, because the client and server have a lot more to negotiate and agree on. The full sequence is in MS-RDPBCGR, but the main phases are:

  1. Negotiation. The client sends an X.224 Connection Request that includes the security protocols it supports: plain RDP security, TLS, or CredSSP (which is what NLA uses). The server picks one based on its own configuration.
  2. TLS and NLA. If TLS or CredSSP was chosen, a normal TLS handshake happens next. With NLA, the client then proves the user’s identity using CredSSP, which runs NTLM or Kerberos inside the TLS tunnel.
  3. Basic settings exchange. The client sends an MCS Connect Initial packet carrying a block of client data: the desired screen size, color depth, keyboard layout, monitor layout, and the list of static virtual channels it wants to open (for example cliprdr for clipboard and rdpsnd for audio). The server responds with its own data and assigns an ID to each channel.
  4. Channel connection. The client joins each channel.
  5. Client info. The client sends user and session information, such as the time zone, the performance flags it wants (like disabling wallpaper or font smoothing on slow links), and optionally credentials for automatic logon.
  6. Capabilities exchange. The server sends a Demand Active PDU listing its capability sets, and the client answers with a Confirm Active PDU listing its own. There are capability sets for general settings, bitmaps, drawing orders, pointers, input, sound, caching, and more. Both sides use the overlap of what they support for the rest of the session.
  7. Finalization. A few short synchronization messages, and the session starts.

The capability exchange above makes sure that both the client and server know what the other side can handle. It’s how a 2026 server can still talk to a 2008 client, and how a thin client with a weak CPU can ask for simpler graphics than a powerful workstation.

How RDP graphics have evolved over time

RDP’s graphics model has changed more than any other part of the protocol, which is how it’s kept up with 4K displays and modern graphics workloads.

Drawing orders (the original approach). Early Windows drew almost everything through GDI, its 2D graphics API. Instead of capturing pixels, the RDP server hooked into GDI and forwarded the drawing calls themselves: “fill this rectangle,” “draw this line,” “draw these glyphs at this position,” “copy this bitmap from cache slot 12.” The client executed the same operations locally.

This is extremely efficient for productivity workloads and typical business desktop usage. Drawing a line of text costs a few bytes once the font’s glyphs are cached on the client, and opening a menu that the client has already seen might cost almost nothing, as the bitmaps are in the cache. This is why RDP was usable over a 28.8 kbps modem in 1998, when sending the equivalent pixels would have been impossible.

Bitmap updates and RemoteFX. As desktops moved to translucent windows, GPU-composited effects, and rich web content, fewer things were drawn with simple GDI calls. RDP added better bitmap compression, and in Windows 7 SP1 Microsoft introduced RemoteFX, a codec built for full-screen rich content.

The Graphics Pipeline (RDP 8 and later). The modern approach is defined in MS-RDPEGFX, the Graphics Pipeline Extension. Instead of drawing orders, the server manages a set of surfaces on the client and updates them with whatever codec fits the content best. The options include:

  • Planar and ClearCodec for lossless compression of UI elements and text.
  • Progressive RemoteFX, which sends a rough version of an image first and refines it over the next few frames.
  • H.264 (AVC420 and AVC444), the same video codec used by most streaming services. AVC420 uses standard 4:2:0 chroma subsampling, which can make colored text look slightly fuzzy. AVC444 sends extra data so the client can rebuild full color resolution, which keeps text sharp.

H.264 matters because it can be encoded and decoded in dedicated hardware on almost every modern CPU and GPU. Instead of the CPU comparing frames and compressing rectangles, a hardware video encoder does the work in a few milliseconds while using very little power. The client can also decode in hardware.

The Graphics Pipeline is server-push with flow control. The server sends frames as the screen changes, and the client sends a Frame Acknowledge message after it processes each one. The server uses those acknowledgments to see how far behind the client is, and adjusts its frame rate or quality to match. That’s a big contrast with RFB, where the client has to ask for each update.

How RDP uses virtual channels for extra features

Remember the MCS (Multipoint Communication Service) channels from earlier? RDP uses them to carry a long list of extra features, each defined in its own spec. These are called virtual channels.

Static virtual channels are set up during the connection sequence. The classic ones are:

  • cliprdr: clipboard, including rich text, images, and file copy and paste
  • rdpsnd: audio playback from the server to the client
  • rdpdr: device redirection, used for local drives, printers, and smart cards
  • drdynvc: the dynamic virtual channel manager

Dynamic virtual channels can be opened and closed at any point during the session, all multiplexed over drdynvc. Most newer features use them, including the Graphics Pipeline itself, microphone input, touch and pen input, USB redirection, and the Display Control channel. Display Control lets the client tell the server “the window is now 2560 by 1440” so the server can change its resolution to match. That’s why resizing an RDP window gives you a sharp desktop at the new size instead of a scaled one.

This channel model is the main reason RDP feels like more than a screen viewer. Audio, clipboard, drives, and printers are all part of the protocol, so any compliant client and server can use them without extra plugins.

How RDP handles input

RDP sends keyboard input as scan codes, which identify the physical key that was pressed, along with flags for key up, key down, and extended keys. The server applies its own keyboard layout, which was negotiated during the connection. This mirrors how a real keyboard works, so shortcuts and international layouts tend to behave correctly. For cases where a scan code doesn’t make sense, like text from an on-screen keyboard or an input method, RDP can also send Unicode characters directly.

Mouse input supports absolute positions, extra buttons, and both vertical and horizontal wheel events. Later extensions add multi-touch and pen input with pressure and tilt.

How RDP uses TCP and UDP

Originally RDP ran only over TCP. TCP guarantees that every byte arrives in order, which is what you want for clipboard data or file transfers, but it’s a problem for real-time graphics. If one packet is lost, everything behind it waits until it’s retransmitted, which shows up as a sudden freeze.

RDP 8 added a UDP transport, defined in MS-RDPEUDP and MS-RDPEMT. The session starts over TCP as usual, then the client and server set up a parallel UDP connection and move graphics and other latency-sensitive traffic onto it. The UDP transport has its own reliable mode and a lossy mode with forward error correction, so a lost packet can often be rebuilt from extra data without waiting for a retransmit. On a clean local network the difference is small, but on Wi-Fi or long-distance links it makes sessions noticeably smoother.

How RDP sessions differ from physical screens

One more big difference from VNC: on Windows Server and most Windows editions, RDP doesn’t show you what’s on your physical monitor. It logs you into a session, which might be a brand-new desktop that exists only for your connection. The session’s resolution is set by your client, not by whatever monitor is plugged into the server.

VNC almost always mirrors the physical screen. If someone is sitting at the machine, they see exactly what you see, and you see exactly what they see at the same resolution.

Neither approach is better in every case. Mirroring is what you want for helping someone else with their computer. A separate session sized to your client is what you want for doing your own work on a remote machine. While Windows doesn’t give you control over what type of screen is shared, many third-party RDP servers like FreeRDP and ProRDP provide more flexibility.

Side-by-side comparison of VNC and RDP

Taking all the above history and technical details into account, here’s a side-by-side comparison of VNC and RDP:

VNC (RFB)RDP
OriginOlivetti & Oracle Research Lab, 1998Microsoft, Windows NT 4.0 TSE, 1998
SpecificationRFC 6143 plus per-vendor extensionsMicrosoft Open Specifications (MS-RDPBCGR and dozens of extensions)
Default portTCP 5900TCP and UDP 3389
Graphics modelChanged pixel rectanglesOriginally drawing orders, now surfaces with H.264 and other codecs
Update flowClient requests each updateServer pushes frames with client acknowledgments
Hardware encodingRareStandard with H.264
TransportTCPTCP, plus optional UDP with error correction
EncryptionNot in the base spec, added by extensionsTLS by default, NLA with CredSSP
ResolutionServer’s screen resolutionClient chooses, can change on resize
AudioNot in the base specBuilt in, both playback and microphone
ClipboardLatin-1 text in the base specRich text, images, and files
Drive and printer redirectionImplementation-specificBuilt in
Keyboard inputX11 keysymsScan codes, with Unicode fallback
Multiple viewers on one screenBuilt inNot the usual model

When to use VNC or RDP

VNC is a good fit when:

  • You need to connect to something unusual, like an embedded device, a hypervisor console, or a minimal Linux install. Odds are it already speaks VNC.
  • You want several people to watch the same screen at once.
  • You’re helping someone and need to see exactly what’s on their monitor.
  • You’re on a fast local network and the content is mostly static, so the pixel-based approach doesn’t hurt much.
  • You want something simple enough to understand completely or build yourself.

RDP is a good fit when:

  • You’re doing real work on the remote machine for long stretches and want it to feel local.
  • You’re on Wi-Fi, a VPN, or any link with real latency or packet loss.
  • You want audio, a full clipboard, or access to your local drives in the remote session.
  • You want the remote desktop to match your client’s resolution and DPI instead of scaling the server’s screen.
  • You want encryption and modern authentication without having to set up a tunnel yourself.

What about VNC and RDP on a Mac?

macOS ships with a VNC-based server built in, which Apple calls Screen Sharing. It uses Apple’s own authentication and some private extensions, but the underlying model is RFB. Apple did add a “High Performance” mode in macOS Sonoma, though it only works between Apple silicon Macs and isn’t available to standard VNC or RDP clients on other platforms, like Windows.

That gap is the reason I built ProRDP. It’s a native RDP server for macOS that uses the Graphics Pipeline with hardware H.264 encoding on the Mac, so any standard RDP client, including the one built into Windows, can connect with the performance and features described above. If you want the background on why I started the project, the announcement post covers it.

Download for macOS

macOS 15 Sequoia or later · Apple silicon & Intel

Further reading

If you want to go deeper into either protocol, the primary sources are very readable: