Exposition formats As of Prometheus version 2.0, all processes that expose metrics to Prometheus must use a text format, by default. An alternative, protobuf format may be used behind the HTTP negotiation. There are various client libraries that implement those formats for you. If your preferred language doesn't have a client library you can create your own. This document outlines officially supported exposition formats. Prometheus Text Format In this section you can find some basic information about this format as well as a more detailed breakdown of the format. Basic info Aspect Description Inception April 2014 Supported in Prometheus version >=0.4.0 Transmission HTTP Encoding UTF-8, \n line endings HTTP Content-Type text/plain with parameters: version=0.0.4 (A missing version value will lead to a fall-back to the most recent text format version.) Optional HTTP Content-Encoding gzip Advantages Human-readable Easy to assemble, especially for minimalistic cases (no nesting required) Readable line by line (with the exception of metadata) Limitations Verbose Types and docstrings not integral part of the syntax, meaning little-to-nonexistent metric contract validation Parsing cost Supported metric primitives Counter Gauge Histogram Summary Untyped Supported advanced features Details Prometheus' text-based format is line oriented. Lines are separated by a line feed character ( \n). The last line must end with a line feed character. Empty lines are ignored. Line format Within a line, tokens can be separated by any number of blanks and/or tabs (and must be separated by at least one if they would otherwise merge with the previous token). Leading and trailing whitespace is ignored. Comments, help text, and type information Lines with a # as the first non-whitespace character are comments. They are ignored unless the first token after # is either HELP or TYPE. Those lines are treated as follows: If the token is HELP, at least one more token is expected, which is the metric name. All remaining tokens are considered the docstring for that metric name. HELP lines may contain any sequence of UTF-8 characters (after the metric name), but the backslash and the line feed characters have to be escaped as \\ and \n, respectively. Only one HELP line may exist for any given metric name. If the token is TYPE, exactly two more tokens are expected. The first is the metric name, and the second is either counter, gauge, histogram, summary, or untyped, defining the type for the metric of that name. Only one TYPE line may exist for a given metric name. The TYPE line for a metric name must appear before the first sample is reported for that metric name. If there is no TYPE line for a metric name, the type is set to untyped. Metric names not corresponding to the legacy Prometheus metric name character set must be quoted and escaped. The remaining lines describe samples (one per line) using the following syntax (EBNF): metric_name_or_labels value [ timestamp ] metric_name_or_labels = metric_name [ "{" labels "}" ] | "{" quoted_metric_name [ "," labels ] "}" metric_name = identifier quoted_metric_name = `"` escaped_string `"` labels = [ label_pairs ] label_pairs = label_pair { "," label_pair } [ "," ] label_pair = label_name "=" `"` escaped_string `"` label_name = identifier | `"` escaped_string `"` In the sample syntax: identifier carries the usual Prometheus expression language restrictions. escaped_string consists of any UTF-8 characters, but backslash, double-quote, and line feed must be escaped. When metric_name is quoted with double quotes, it appears inside the braces instead of outside. label_name may be optionally enclosed in double quotes. Metric and label names not corresponding to the usual Prometheus expression language restrictions must use the quoted syntaxes. label_value can be any sequence of UTF-8 characters, but the backslash ( \), double-quote ( "), and line feed ( \n) characters have to be escaped as \\, \", and \n, respectively. value is a float represented as required by Go's ParseFloat() function. In addition to standard numerical values, NaN, +Inf, and -Inf are valid values representing not a number, positive infinity, and negative infinity, respectively. The timestamp is an int64 (milliseconds since epoch, i.e. 1970-01-01 00:00:00 UTC, excluding leap seconds), represented as required by Go's ParseInt() function. Grouping and sorting All lines for a given metric must be provided as one single group, with the optional HELP and TYPE lines first (in no particular order). Beyond that, reproducible sorting in repeated expositions is preferred but not required, i.e. do not sort if the computational cost is prohibitive. Each line must have a unique combination of a metric name and labels. Otherwise, the ingestion behavior is undefined. Histograms and summaries The histogram and summary types are difficult to represent in the text format. The following conventions apply: The sample sum for a summary or histogram named x is given as a separate sample named x_sum. The sample count for a summary or histogram named x is given as a separate sample named x_count. Each quantile of a summary named x is given as a separate sample line with the same name x and a label {quantile="y"}. Each bucket count of a histogram named x is given as a separate sample line with the name x_bucket and a label {le="y"} (where y is the upper bound of the bucket). A histogram must have a bucket with {le="+Inf"}. Its value must be identical to the value of x_count. The buckets of a histogram and the quantiles of a summary must appear in increasing numerical order of their label values (for the le or the quantile label, respectively). Example Below is an example of a full-fledged Prometheus metric exposition, including comments, HELP and TYPE expressions, a histogram, a summary, character escaping examples, and more. # HELP http_requests_total The total number of HTTP requests. # TYPE http_requests_total counter http_requests_total{method="post",code="200"} 1027 1395066363000 http_requests_total{method="post",code="400"} 3 1395066363000 # Escaping in label values: msdos_file_access_time_seconds{path="C:\\DIR\\FILE.TXT",error="Cannot find file:\n\"FILE.TXT\""} 1.458255915e9 # UTF-8 metric and label names: {"my.dotted.metric", "error.message"="Not Found"} # Minimalistic line: metric_without_timestamp_and_labels 12.47 # A weird metric from before the epoch: something_weird{problem="division by zero"} +Inf -3982045 # A histogram, which has a pretty complex representation in the text format: # HELP http_request_duration_seconds A histogram of the request duration. # TYPE http_request_duration_seconds histogram http_request_duration_seconds_bucket{le="0.05"} 24054 http_request_duration_seconds_bucket{le="0.1"} 33444 http_request_duration_seconds_bucket{le="0.2"} 100392 http_request_duration_seconds_bucket{le="0.5"} 129389 http_request_duration_seconds_bucket{le="1"} 133988 http_request_duration_seconds_bucket{le="+Inf"} 144320 http_request_duration_seconds_sum 53423 http_request_duration_seconds_count 144320 # Finally a summary, which has a complex representation, too: # HELP rpc_duration_seconds A summary of the RPC duration in seconds. # TYPE rpc_duration_seconds summary rpc_duration_seconds{quantile="0.01"} 3102 rpc_duration_seconds{quantile="0.05"} 3272 rpc_duration_seconds{quantile="0.5"} 4773 rpc_duration_seconds{quantile="0.9"} 9001 rpc_duration_seconds{quantile="0.99"} 76656 rpc_duration_seconds_sum 1.7560473e+07 rpc_duration_seconds_count 2693 OpenMetrics Text Format OpenMetrics is an effort to standardize metric wire formatting built off of Prometheus text format. It is possible to scrape targets, and it is also available to use for federating metrics since Prometheus v2.23.0. There are currently two versions of OpenMetrics: 1.0 2.0 (draft) Basic info Aspect Description Inception November 2020 Supported in Prometheus version >=2.5.0 Transmission HTTP Encoding UTF-8, \n line endings, trailed with # EOF. HTTP Content-Type application/openmetrics-text with parameters: version=1.0.0 (a missing version value will lead to a fall-back to the most recent text OpenMetrics version.) Optional HTTP Content-Encoding gzip Advantages Human-readable Easy to assemble, especially for minimalistic cases (no nesting required) Readable line by line (with the exception of metadata) Limitations Verbose Types and docstrings not integral part of the syntax, meaning little-to-nonexistent metric contract validation Parsing cost Supported metric primitives Counter Gauge Histogram GaugeHistogram Summary Info StateSet Untyped Supported advanced features Unit metadata Exemplars (Counters, Histogram, GaugeHistogram) Created/Start Timestamps (Counter, Histogram, GaugeHistogram, Summary) UTF-8 metric names and label names Exemplars (Experimental) Utilizing the OpenMetrics format allows for the exposition and querying of Exemplars. Exemplars provide a point in time snapshot related to a metric set for an otherwise summarized MetricFamily. Additionally, they may have a Trace ID attached to them which when used to together with a tracing system can provide more detailed information related to the specific service. To enable this experimental feature you must have at least version v2.26.0 and add --enable-feature=exemplar-storage to your arguments. Prometheus Protobuf Format Prometheus officially supports protobuf exposition format in addition to the text representation. The payload must be encoded as a set of Protobuf messages representing MetricFamily. Messages must be encoded in binary and prepended with their variadic unsigned-integer encoded size, which serves as a delimitation. The varint encoded size delimited encoding offers streaming capabilities, especially important for large scrape targets. All string fields must be UTF-8 encoded. Prometheus 3.0 prefers the text-based protocols by default unless: Manual preference settings via scrape_protocols setting in Prometheus configuration. Protobuf format first when certain features are enabled e.g.: --enable-feature=created-timestamp-zero-ingestion or --enable-feature=st-storage Appropriate configuration option ( scrape_native_histograms: true) In Prometheus 2.0, the Protobuf format was marked as deprecated, but since then this decision was reverted. From Prometheus 3.0, the Prometheus Proto is actively used and maintained, supplementing text-based formats. Basic info Aspect Description Inception April 2014 Supported in Prometheus version >=0.4.0 Transmission HTTP Encoding 32-Bit Varint-Encoded Record Length-Delimited Protocol Buffer Messages of io.prometheus.client.MetricFamily HTTP Content-Type application/vnd.google.protobuf with parameters: proto=io.prometheus.client.MetricFamily encoding=delimited Optional HTTP Content-Encoding gzip Advantages Cross-Platform Size Forward/Backward Compatibility Strict Schema Supports Concatenation and Streaming Composite Values Limitations Not human readable Supported metric primitives Counter Gauge Histogram GaugeHistogram Summary Untyped Supported advanced features Unit metadata Exemplars (Counters, Histogram, GaugeHistogram) Created/Start Timestamps (Counter, Histogram, GaugeHistogram, Summary) Native (sparse and exponential) Histogram, GaugeHistogram UTF-8 metric names and label names When to use Proto over Text? The text format is human-readable, compresses well and is efficient enough for programming use, but Prometheus community also maintains the protobuf formats, because: It increases the quality and velocity of new features that can be safely tested in the backward/forward compatible way. Protobuf helps with the exposer/ingestor implementations, given the code generation and flexibility features. In (surprisingly rare) cases binary encoding can be more efficiently encoded/decoded. You can learn more in the PromCon 2025 talk. Versioning At the moment Prometheus protobuf is stable, but explicitly unversioned. Instead, it follows Prometheus versioning as a reference. Schema Protobuf schema, identified as io.prometheus.client is maintained in Prometheus repository here. Schema is also available in buf registry. HTTP Content-Type requirements Starting with Prometheus 3.0, scrape targets must return a valid Content-Type header for the metrics endpoint. If the Content-Type is missing, unparsable, or not a supported media type, the scrape will fail. See changes in scrape protocols in the migration guide for details. See each of the exposition format sections for the accurate HTTP content types. ScrapeProtocols vs Content-Type Prometheus scrape config offers scrape protocol negotiation based on the content-type using the scrape_protocols config. For the Prometheus user convenience the scrape protocols are referenced by a unique name that maps to the concrete content-type. See Protocol Headers for details. However, the targets should expose metrics in the exposition format with the absolute, response content-type (e.g. application/openmetrics-text;version=1.0.0) and only one. Historical versions For details on historical format versions, see the legacy Client Data Exposition Format document. The current version of the original Protobuf format (with the recent extensions for native histograms) is maintained in the prometheus/client_model repository.