diff --git a/src/http_act.c b/src/http_act.c
index bfe8321d8..6f6d78222 100644
--- a/src/http_act.c
+++ b/src/http_act.c
@@ -20,6 +20,7 @@
 #include <haproxy/action.h>
 #include <haproxy/api.h>
 #include <haproxy/arg.h>
+#include <haproxy/base64.h>
 #include <haproxy/capture-t.h>
 #include <haproxy/cfgparse.h>
 #include <haproxy/chunk.h>
@@ -1414,6 +1415,106 @@ static enum act_return http_action_early_hint(struct act_rule *rule, struct prox
 	goto leave;
 }
 
+/* This function executes a set-headers-bin or add-headers-bin actions.
+*/
+
+static enum act_return http_action_set_headers_bin(struct act_rule *rule, struct proxy *px,
+					      struct session *sess, struct stream *s, int flags)
+{
+	struct http_msg *msg = ((rule->from == ACT_F_HTTP_REQ) ? &s->txn->req : &s->txn->rsp);
+	struct htx *htx = htxbuf(&msg->chn->buf);
+	enum act_return ret = ACT_RET_CONT;
+	struct buffer *binstring, *decoded;
+	struct http_hdr_ctx ctx;
+	struct ist n, v;
+	uint64_t sz;
+	char *oldarea;
+
+	binstring = alloc_trash_chunk();
+	if (!binstring)
+		goto fail_alloc_binstring;
+	decoded = alloc_trash_chunk();
+	if (!decoded)
+		goto fail_alloc_decoded;
+
+	binstring->data = build_logline(s, binstring->area, binstring->size, &rule->arg.http.fmt);
+	decoded->data = base64dec(binstring->area, binstring->data, decoded->area, decoded->size);
+
+	while (1) {
+		oldarea = decoded->area;
+		if (decode_varint(&decoded->area, decoded->area + decoded->data, &sz) == -1)
+			goto fail_rewrite;
+
+		decoded->data -= (decoded->area - oldarea);
+
+		if (!sz) {
+			if (decode_varint(&decoded->area, decoded->area + decoded->data, &sz) == -1)
+				goto fail_rewrite;
+			if (!sz)
+				goto leave;
+			else
+				goto fail_rewrite;
+		}
+
+		n = ist2(decoded->area, sz);
+		decoded->area += sz;
+		decoded->data -= sz;
+		oldarea = decoded->area;
+
+		if (decode_varint(&decoded->area, decoded->area + decoded->data, &sz) == -1)
+			goto fail_rewrite;
+
+		decoded->data -= (decoded->area - oldarea);
+
+		v = ist2(decoded->area, sz);
+		decoded->area += sz;
+		decoded->data -= sz;
+
+		if (rule->action == 0) { // set-header
+			/* remove all occurrences of the header */
+			ctx.blk = NULL;
+			while (http_find_header(htx, n, &ctx, 1))
+				http_remove_header(htx, &ctx);
+		}
+
+		/* Now add header */
+		if (!http_add_header(htx, n, v))
+			goto fail_rewrite;
+	}
+
+  leave:
+	free_trash_chunk(binstring);
+	return ret;
+
+  fail_alloc_decoded:
+	free_trash_chunk(decoded);
+
+  fail_alloc_binstring:
+	if (!(s->flags & SF_ERR_MASK))
+		s->flags |= SF_ERR_RESOURCE;
+	ret = ACT_RET_ERR;
+	goto leave;
+
+  fail_rewrite:
+	if (sess->fe_tgcounters)
+		_HA_ATOMIC_INC(&sess->fe_tgcounters->failed_rewrites);
+	if ((s->flags & SF_BE_ASSIGNED) && s->be_tgcounters)
+		_HA_ATOMIC_INC(&s->be_tgcounters->failed_rewrites);
+	if (sess->li_tgcounters)
+		_HA_ATOMIC_INC(&sess->li_tgcounters->failed_rewrites);
+	if (s->sv_tgcounters)
+		_HA_ATOMIC_INC(&s->sv_tgcounters->failed_rewrites);
+
+	if (!(msg->flags & HTTP_MSGF_SOFT_RW)) {
+		ret = ACT_RET_ERR;
+		if (!(s->flags & SF_ERR_MASK))
+			s->flags |= SF_ERR_PRXCOND;
+	}
+	goto leave;
+}
+
+
+
 /* This function executes a set-header or add-header actions. It builds a string
  * in the trash from the specified format string. It finds the action to be
  * performed in <.action>, previously filled by function parse_set_header(). The
@@ -1479,6 +1580,51 @@ static enum act_return http_action_set_header(struct act_rule *rule, struct prox
 	goto leave;
 }
 
+/* Parse set-headers-bin */
+static enum act_parse_ret parse_http_set_headers_bin(const char **args, int *orig_arg, struct proxy *px,
+						   struct act_rule *rule, char **err)
+{
+	int cap = 0, cur_arg;
+
+	if (args[*orig_arg-1][0] == 's')
+		rule->action = 0; // set-header
+	else
+		rule->action = 1; // add-header
+	rule->action_ptr = http_action_set_headers_bin;
+
+	rule->release_ptr = release_http_action;
+	lf_expr_init(&rule->arg.http.fmt);
+
+	cur_arg = *orig_arg;
+	if (!*args[cur_arg] || *args[cur_arg+1]) {
+		memprintf(err, "expects exactly argument");
+		return ACT_RET_PRS_ERR;
+	}
+
+	if (rule->from == ACT_F_HTTP_REQ) {
+		px->conf.args.ctx = ARGC_HRQ;
+		if (px->cap & PR_CAP_FE)
+			cap |= SMP_VAL_FE_HRQ_HDR;
+		if (px->cap & PR_CAP_BE)
+			cap |= SMP_VAL_BE_HRQ_HDR;
+	}
+	else{
+		px->conf.args.ctx =  ARGC_HRS;
+		if (px->cap & PR_CAP_FE)
+			cap |= SMP_VAL_FE_HRS_HDR;
+		if (px->cap & PR_CAP_BE)
+			cap |= SMP_VAL_BE_HRS_HDR;
+	}
+
+	if (!parse_logformat_string(args[cur_arg], px, &rule->arg.http.fmt, LOG_OPT_HTTP, cap, err)) {
+		istfree(&rule->arg.http.str);
+		return ACT_RET_PRS_ERR;
+	}
+
+	*orig_arg = cur_arg + 1;
+	return ACT_RET_PRS_OK;
+}
+
 /* Parse a "set-header", "add-header" or "early-hint" actions. It takes an
  * header name and a log-format string as arguments. It returns ACT_RET_PRS_OK
  * on success, ACT_RET_PRS_ERR on error.
@@ -2509,6 +2655,7 @@ static struct action_kw_list http_req_actions = {
 	.kw = {
 		{ "add-acl",          parse_http_set_map,              KWF_MATCH_PREFIX },
 		{ "add-header",       parse_http_set_header,           0 },
+		{ "add-headers-bin",  parse_http_set_headers_bin,      0 },
 		{ "allow",            parse_http_allow,                0 },
 		{ "auth",             parse_http_auth,                 0 },
 		{ "capture",          parse_http_req_capture,          0 },
@@ -2530,6 +2677,7 @@ static struct action_kw_list http_req_actions = {
 		{ "replace-value",    parse_http_replace_header,       0 },
 		{ "return",           parse_http_return,               0 },
 		{ "set-header",       parse_http_set_header,           0 },
+		{ "set-headers-bin",  parse_http_set_headers_bin,      0 },
 		{ "set-map",          parse_http_set_map,              KWF_MATCH_PREFIX },
 		{ "set-method",       parse_set_req_line,              0 },
 		{ "set-path",         parse_set_req_line,              0 },
@@ -2549,27 +2697,29 @@ INITCALL1(STG_REGISTER, http_req_keywords_register, &http_req_actions);
 
 static struct action_kw_list http_res_actions = {
 	.kw = {
-		{ "add-acl",         parse_http_set_map,        KWF_MATCH_PREFIX },
-		{ "add-header",      parse_http_set_header,     0 },
-		{ "allow",           parse_http_allow,          0 },
-		{ "capture",         parse_http_res_capture,    0 },
-		{ "del-acl",         parse_http_set_map,        KWF_MATCH_PREFIX },
-		{ "del-header",      parse_http_del_header,     0 },
-		{ "del-map",         parse_http_set_map,        KWF_MATCH_PREFIX },
-		{ "deny",            parse_http_deny,           0 },
-		{ "do-log",          parse_http_res_do_log,     0 },
-		{ "pause",           parse_http_pause,          0 },
-		{ "redirect",        parse_http_redirect,       0 },
-		{ "replace-header",  parse_http_replace_header, 0 },
-		{ "replace-value",   parse_http_replace_header, 0 },
-		{ "return",          parse_http_return,         0 },
-		{ "set-header",      parse_http_set_header,     0 },
-		{ "set-map",         parse_http_set_map,        KWF_MATCH_PREFIX },
-		{ "set-status",      parse_http_set_status,     0 },
-		{ "strict-mode",     parse_http_strict_mode,    0 },
-		{ "track-sc",        parse_http_track_sc,       KWF_MATCH_PREFIX },
-		{ "set-timeout",     parse_http_set_timeout,    0 },
-		{ "wait-for-body",   parse_http_wait_for_body,  0 },
+		{  "add-acl",         parse_http_set_map,         KWF_MATCH_PREFIX },
+		{  "add-header",      parse_http_set_header,      0 },
+		{  "add-headers-bin", parse_http_set_headers_bin, 0 },
+		{  "allow",           parse_http_allow,           0 },
+		{  "capture",         parse_http_res_capture,     0 },
+		{  "del-acl",         parse_http_set_map,         KWF_MATCH_PREFIX },
+		{  "del-header",      parse_http_del_header,      0 },
+		{  "del-map",         parse_http_set_map,         KWF_MATCH_PREFIX },
+		{  "deny",            parse_http_deny,            0 },
+		{  "do-log",          parse_http_res_do_log,      0 },
+		{  "pause",           parse_http_pause,           0 },
+		{  "redirect",        parse_http_redirect,        0 },
+		{  "replace-header",  parse_http_replace_header,  0 },
+		{  "replace-value",   parse_http_replace_header,  0 },
+		{  "return",          parse_http_return,          0 },
+		{  "set-header",      parse_http_set_header,      0 },
+		{  "set-headers-bin", parse_http_set_headers_bin, 0 },
+		{  "set-map",         parse_http_set_map,         KWF_MATCH_PREFIX },
+		{  "set-status",      parse_http_set_status,      0 },
+		{  "strict-mode",     parse_http_strict_mode,     0 },
+		{  "track-sc",        parse_http_track_sc,        KWF_MATCH_PREFIX },
+		{  "set-timeout",     parse_http_set_timeout,     0 },
+		{  "wait-for-body",   parse_http_wait_for_body,   0 },
 		{ NULL, NULL }
 	}
 };
