diff --git a/CHANGELOG.md b/CHANGELOG.md
index 48ed6e0d..a808a5b7 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,10 +9,16 @@ CHANGELOG
     - fzf will automatically choose `path` scheme when the input is a TTY device, where fzf would start its built-in walker or run `$FZF_DEFAULT_COMMAND` which is usually a command for listing files.
 - Added `--header-lines-border` to display header from `--header-lines` with a separate border
   ```sh
+  # Use --header-lines-border to separate two headers
   ps -ef | fzf --style full --layout reverse --header-lines 1 \
                --bind 'ctrl-r:reload(ps -ef)' --header 'Press CTRL-R to reload' \
                --header-lines-border bottom --no-list-border
   ```
+- Added `bell` action to ring the terminal bell
+  ```sh
+  # Press CTRL-Y to copy the current line to the clipboard and ring the bell
+  fzf --bind 'ctrl-y:execute-silent(echo -n {} | pbcopy)+bell'
+  ```
 - Bug fixes and improvements
 - Fixed fish script to support fish 3.1.2 or later (@bitraid)
 
diff --git a/man/man1/fzf.1 b/man/man1/fzf.1
index b7e4ec6d..2377ba03 100644
--- a/man/man1/fzf.1
+++ b/man/man1/fzf.1
@@ -1541,6 +1541,7 @@ A key or an event can be bound to one or more of the following actions.
     \fBbackward\-word\fR                \fIalt\-b   shift\-left\fR
     \fBbecome(...)\fR                  (replace fzf process with the specified command; see below for the details)
     \fBbeginning\-of\-line\fR            \fIctrl\-a  home\fR
+    \fBbell\fR                         (ring the terminal bell)
     \fBcancel\fR                       (clear query string if not empty, abort fzf otherwise)
     \fBchange\-border\-label(...)\fR     (change \fB\-\-border\-label\fR to the given string)
     \fBchange\-header(...)\fR           (change header to the given string; doesn't affect \fB\-\-header\-lines\fR)
diff --git a/src/options.go b/src/options.go
index d31b1001..9d233b57 100644
--- a/src/options.go
+++ b/src/options.go
@@ -1586,6 +1586,8 @@ func parseActionList(masked string, original string, prevActions []*action, putA
 			} else {
 				return nil, errors.New("unable to put non-printable character")
 			}
+		case "bell":
+			appendAction(actBell)
 		default:
 			t := isExecuteAction(specLower)
 			if t == actIgnore {
diff --git a/src/terminal.go b/src/terminal.go
index 4d577fc5..30523de3 100644
--- a/src/terminal.go
+++ b/src/terminal.go
@@ -567,6 +567,7 @@ const (
 	actBecome
 	actShowHeader
 	actHideHeader
+	actBell
 )
 
 func (a actionType) Name() string {
@@ -4704,6 +4705,8 @@ func (t *Terminal) Loop() error {
 						t.executor.Become(t.ttyin, t.environ(), command)
 					}
 				}
+			case actBell:
+				t.tui.Bell()
 			case actExecute, actExecuteSilent:
 				t.executeCommand(a.a, false, a.t == actExecuteSilent, false, false, "")
 			case actExecuteMulti:
diff --git a/src/tui/dummy.go b/src/tui/dummy.go
index 1e62e849..1cfb292e 100644
--- a/src/tui/dummy.go
+++ b/src/tui/dummy.go
@@ -44,6 +44,7 @@ func (r *FullscreenRenderer) PassThrough(string)                 {}
 func (r *FullscreenRenderer) Clear()                             {}
 func (r *FullscreenRenderer) NeedScrollbarRedraw() bool          { return false }
 func (r *FullscreenRenderer) ShouldEmitResizeEvent() bool        { return false }
+func (r *FullscreenRenderer) Bell()                              {}
 func (r *FullscreenRenderer) Refresh()                           {}
 func (r *FullscreenRenderer) Close()                             {}
 func (r *FullscreenRenderer) Size() TermSize                     { return TermSize{} }
diff --git a/src/tui/light.go b/src/tui/light.go
index f4688060..56e9ae0b 100644
--- a/src/tui/light.go
+++ b/src/tui/light.go
@@ -32,6 +32,10 @@ const consoleDevice string = "/dev/tty"
 var offsetRegexp = regexp.MustCompile("(.*)\x1b\\[([0-9]+);([0-9]+)R")
 var offsetRegexpBegin = regexp.MustCompile("^\x1b\\[[0-9]+;[0-9]+R")
 
+func (r *LightRenderer) Bell() {
+	r.flushRaw("\a")
+}
+
 func (r *LightRenderer) PassThrough(str string) {
 	r.queued.WriteString("\x1b7" + str + "\x1b8")
 }
diff --git a/src/tui/tcell.go b/src/tui/tcell.go
index 0bf160c4..3c3e13fc 100644
--- a/src/tui/tcell.go
+++ b/src/tui/tcell.go
@@ -100,6 +100,10 @@ const (
 	BoldForce     = Attr(1 << 10)
 )
 
+func (r *FullscreenRenderer) Bell() {
+	_screen.Beep()
+}
+
 func (r *FullscreenRenderer) PassThrough(str string) {
 	// No-op
 	// https://github.com/gdamore/tcell/pull/650#issuecomment-1806442846
diff --git a/src/tui/tui.go b/src/tui/tui.go
index 32aefc79..eab5ad7e 100644
--- a/src/tui/tui.go
+++ b/src/tui/tui.go
@@ -580,6 +580,7 @@ type Renderer interface {
 	PassThrough(string)
 	NeedScrollbarRedraw() bool
 	ShouldEmitResizeEvent() bool
+	Bell()
 
 	GetChar() Event