diff --git a/compiler/ml/unified_ops.ml b/compiler/ml/unified_ops.ml
index 997606135e..99ad08e353 100644
--- a/compiler/ml/unified_ops.ml
+++ b/compiler/ml/unified_ops.ml
@@ -187,6 +187,19 @@ let entries =
           string = None;
         };
     };
+    {
+      path = builtin "|";
+      name = "%bitor";
+      form = Binary;
+      specialization =
+        {
+          int = Porint;
+          bool = None;
+          float = None;
+          bigint = Some Porbigint;
+          string = None;
+        };
+    };
   |]
 
 let index_by_path =
diff --git a/compiler/syntax/src/res_parsetree_viewer.ml b/compiler/syntax/src/res_parsetree_viewer.ml
index 5305bd3fc2..f33c2e16c1 100644
--- a/compiler/syntax/src/res_parsetree_viewer.ml
+++ b/compiler/syntax/src/res_parsetree_viewer.ml
@@ -272,12 +272,13 @@ let operator_precedence operator =
   | ":=" -> 1
   | "||" -> 2
   | "&&" -> 3
-  | "^" -> 4
-  | "==" | "===" | "<" | ">" | "!=" | "<>" | "!==" | "<=" | ">=" | "|>" -> 5
-  | "+" | "+." | "-" | "-." | "++" -> 6
-  | "*" | "*." | "/" | "/." | "%" -> 7
-  | "**" -> 8
-  | "#" | "##" | "->" -> 9
+  | "|" -> 4
+  | "^" -> 5
+  | "==" | "===" | "<" | ">" | "!=" | "<>" | "!==" | "<=" | ">=" | "|>" -> 6
+  | "+" | "+." | "-" | "-." | "++" -> 7
+  | "*" | "*." | "/" | "/." | "%" -> 8
+  | "**" -> 9
+  | "#" | "##" | "->" -> 10
   | _ -> 0
 
 let is_unary_operator operator =
@@ -300,7 +301,7 @@ let is_binary_operator operator =
   match operator with
   | ":=" | "||" | "&&" | "==" | "===" | "<" | ">" | "!=" | "!==" | "<=" | ">="
   | "|>" | "+" | "+." | "-" | "-." | "++" | "*" | "*." | "/" | "/." | "**"
-  | "->" | "<>" | "%" | "^" ->
+  | "->" | "<>" | "%" | "^" | "|" ->
     true
   | _ -> false
 
diff --git a/compiler/syntax/src/res_token.ml b/compiler/syntax/src/res_token.ml
index 29d2b503d4..595e6bdbc3 100644
--- a/compiler/syntax/src/res_token.ml
+++ b/compiler/syntax/src/res_token.ml
@@ -79,6 +79,7 @@ type t =
   | Lor
   | Band (* Bitwise and: & *)
   | Caret
+
   | BangEqual
   | BangEqualEqual
   | LessEqual
@@ -103,15 +104,16 @@ let precedence = function
   | HashEqual | ColonEqual -> 1
   | Lor -> 2
   | Land -> 3
-  | Caret -> 4
+  | Bar -> 4
+  | Caret -> 5
   | Equal | EqualEqual | EqualEqualEqual | LessThan | GreaterThan | BangEqual
   | BangEqualEqual | LessEqual | GreaterEqual | BarGreater ->
-    5
-  | Plus | PlusDot | Minus | MinusDot | PlusPlus -> 6
-  | Asterisk | AsteriskDot | Forwardslash | ForwardslashDot | Percent -> 7
-  | Exponentiation -> 8
-  | MinusGreater -> 9
-  | Dot -> 10
+    6
+  | Plus | PlusDot | Minus | MinusDot | PlusPlus -> 7
+  | Asterisk | AsteriskDot | Forwardslash | ForwardslashDot | Percent -> 8
+  | Exponentiation -> 9
+  | MinusGreater -> 10
+  | Dot -> 11
   | _ -> 0
 
 let to_string = function
diff --git a/runtime/Pervasives.res b/runtime/Pervasives.res
index 6d997a603f..c8b5da7831 100644
--- a/runtime/Pervasives.res
+++ b/runtime/Pervasives.res
@@ -68,6 +68,7 @@ external \"%": ('a, 'a) => 'a = "%mod"
 external mod: ('a, 'a) => 'a = "%mod"
 external \"**": ('a, 'a) => 'a = "%pow"
 external \"^": ('a, 'a) => 'a = "%bitxor"
+external \"|": ('a, 'a) => 'a = "%bitor"
 
 /* Comparisons */
 /* Note: Later comparisons will be converted to unified operations too */
diff --git a/tests/syntax_tests/data/parsing/grammar/expressions/binary.res b/tests/syntax_tests/data/parsing/grammar/expressions/binary.res
index 224eb2da39..3c9d60e15f 100644
--- a/tests/syntax_tests/data/parsing/grammar/expressions/binary.res
+++ b/tests/syntax_tests/data/parsing/grammar/expressions/binary.res
@@ -29,6 +29,7 @@ let x = a + -1 + -2
 let x = a + @attr -1 + @attr -2
 let x = a % a == 0
 let x = a ^ a == 0
+let x = a | a == a
 
 // should be interpreted as binary expression not prefix op
 let x = a -b
diff --git a/tests/syntax_tests/data/printer/expr/binary.res b/tests/syntax_tests/data/printer/expr/binary.res
index 6f43115a00..b68f625ca2 100644
--- a/tests/syntax_tests/data/printer/expr/binary.res
+++ b/tests/syntax_tests/data/printer/expr/binary.res
@@ -55,6 +55,7 @@ x + y / z
 x / y + z
 x % y * z
 x ^ y + z
+x | y + z
 100 * x / total
 2 / 3 * 10 / 2 + 2
 let rotateX = ((range / rect.height) * refY - range / 2) * getXMultiplication(rect.width)
diff --git a/tests/tests/src/belt_int_test.res b/tests/tests/src/belt_int_test.res
index 0c77875493..701c7d35df 100644
--- a/tests/tests/src/belt_int_test.res
+++ b/tests/tests/src/belt_int_test.res
@@ -42,5 +42,6 @@ describe(__MODULE__, () => {
     eq(__LOC__, 2 / 3, 0)
     eq(__LOC__, 2 % 2, 0)
     eq(__LOC__, 2 ^ 3, 1)
+    eq(__LOC__, 2 | 3, 3)
   })
 })
diff --git a/tests/tests/src/unified_ops_test.res b/tests/tests/src/unified_ops_test.res
index d98d453837..ffb58efa0f 100644
--- a/tests/tests/src/unified_ops_test.res
+++ b/tests/tests/src/unified_ops_test.res
@@ -29,3 +29,6 @@ let pow_overflow = 2147483647 ** 2
 
 let bxor_int = (a, b) => a ^ b
 let bxor_bigint = (a: bigint, b) => a ^ b
+
+let bitor_int = (a, b) => a | b
+let bitor_bigint = (a: bigint, b) => a | b