HTTP/2 Protocol in Plain English using Wireshark

1. Quick Intro

Some people find it easier to do a "test drive" first to learn how a new protocol works in its simplest form and only then read the RFC. It turns out Wireshark is a perfect tool for me to do just that. 

It's a simple test and here's the topology:

I'll just issue a HEAD request and later on a GET request and we'll see how it looks like on Wireshark.

For more info about HTTP/2 profile and HTTP/2 protocol itself you can read the article I published on AskF5 and Jason's DevCentral article: What is HTTP Part X - HTTP/2

2. Confirmation of which protocol will be used

The packet capture taken below was the result of the following curl command issued from my ubuntu Linux client (I could've used a browser instead):







Note: is my virtual server with HTTP/2 profile applied.

Here's packet capture (in case you want to follow along):  

HTTP/2 is negotiated during SSL handshake in Application Layer Protocol Negotiation (RFC 7301) SSL extension like this: 


Client says which protocol(s) it supports and server responds which one it picked (in this case it's HTTP/2!).

3. Negotiation of HTTP/2 Parameters

Think of it as something that has to take place like Client Hello and Server Hello in SSL for example.

Server side (BIG-IP in this case) sends SETTINGS frame which counts as confirmation that HTTP/2 is being used plus any flow control configuration we want our peer to honour:

Client sends Magic frame to confirm HTTP/2 is being used and then SETTINGS with its requirements for the connection. Yes, Magic frame is always the same.

Still curious about Magic frame? Read

End-points are also supposed to ACK the receipt of SETTINGS frame from the other peer and the way they do it is by responding with another empty SETTINGS frame with ACK flag set:

4. Exchanging data

Connection-wise we're all set now. For HTTP/2 GET/HEAD requests there is a specific frame type called HEADERS which as the name implies carries HTTP/2 header information. 

If there was payload it would be carried inside DATA frame type but as this is just a HEAD request then no DATA frame follows.

5. Appendix A - Other common frame types


There are other common frame types and in my capture the one that came up was WINDOW_UPDATE.

If you look at section 3 above we see that Client advised BIG-IP that its Initial Window Size was 1073741824.

WINDOW_UPDATE just adjusted this value to 1073676289:

This is HTTP/2 flow control in action.

5.2 DATA

in another test ( I used HTTP/2 GET request instead of HEAD and requested more data which comes in through DATA frame type:

End Stream flag is false in all DATA messages except for the last one. It signals when there is more data as well as the last DATA frame.


In a subsequent test ( I set Connection Idle Timeout in HTTP/2 profile to 1 to force BIG-IP sending GOAWAY frame to close down connection after 1 second of idle connection.

After last piece of data is sent by BIG-IP to client (frame #39), BIG-IP waits 1 second and sends GOAWAY frame which initiates the shutdown of HTTP/2 connection.

GOAWAY messages always contains Promised-Stream-ID which tells the client what is the last Stream ID it processed.

A new Stream ID is typically created for every new HTTP request (via HEADERS message).

We can see that a new HTTP request slipped in on frame #46 but ignored as connection had already been closed on BIG-IP's side.

Published Mar 06, 2019
Version 1.0

Was this article helpful?