diff --git a/NEWS.md b/NEWS.md
index 740b7dc4..1f3d01da 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -1,6 +1,8 @@
 profvis 0.3.6.9000
 =============
 
+* Added `simplify` argument. When `TRUE` (the default), the profiles are simplified using the new `filter.callframes` argument of R 4.0. This argument has no effect on older R versions.
+
 * Fixed [#111](https://github.com/rstudio/profvis/issues/111): auto-scrolling to lines of code did not work in some browsers. ([#113](https://github.com/rstudio/profvis/pull/113))
 
 profvis 0.3.6
diff --git a/R/profvis.R b/R/profvis.R
index fd6986c6..7d8366bd 100644
--- a/R/profvis.R
+++ b/R/profvis.R
@@ -32,6 +32,11 @@
 #'   \code{torture = steps} helps prevent this, by making R trigger garbage
 #'   collection after every \code{torture} memory allocation step.
 #'
+#' @param simplify Whether to simplify the profiles by removing
+#'   intervening frames caused by lazy evaluation. This only has an
+#'   effect on R 4.0. See the \code{filter.callframes} argument of
+#'   \code{\link{Rprof}()}.
+#'
 #' @seealso \code{\link{print.profvis}} for printing options.
 #' @seealso \code{\link{Rprof}} for more information about how the profiling
 #'   data is collected.
@@ -75,7 +80,7 @@
 #' @export
 profvis <- function(expr = NULL, interval = 0.01, prof_output = NULL,
                     prof_input = NULL, width = NULL, height = NULL,
-                    split = c("h", "v"), torture = 0)
+                    split = c("h", "v"), torture = 0, simplify = TRUE)
 {
   split <- match.arg(split)
   expr_q <- substitute(expr)
@@ -128,8 +133,14 @@ profvis <- function(expr = NULL, interval = 0.01, prof_output = NULL,
       on.exit(gctorture2(step = 0), add = TRUE)
     }
 
-    Rprof(prof_output, interval = interval, line.profiling = TRUE,
-          gc.profiling = TRUE, memory.profiling = TRUE)
+    if (getRversion() >= "4.0.0") {
+      Rprof(prof_output, interval = interval, line.profiling = TRUE,
+            gc.profiling = TRUE, memory.profiling = TRUE,
+            filter.callframes = simplify)
+    } else {
+      Rprof(prof_output, interval = interval, line.profiling = TRUE,
+            gc.profiling = TRUE, memory.profiling = TRUE)
+    }
     on.exit(Rprof(NULL), add = TRUE)
     if (remove_on_exit)
       on.exit(unlink(prof_output), add = TRUE)
diff --git a/man/profvis.Rd b/man/profvis.Rd
index 97b7e9ed..0636fdb5 100644
--- a/man/profvis.Rd
+++ b/man/profvis.Rd
@@ -12,7 +12,8 @@ profvis(
   width = NULL,
   height = NULL,
   split = c("h", "v"),
-  torture = 0
+  torture = 0,
+  simplify = TRUE
 )
 }
 \arguments{
@@ -45,6 +46,11 @@ split bar.}
   memory allocations will be attributed to different lines of code. Using
   \code{torture = steps} helps prevent this, by making R trigger garbage
   collection after every \code{torture} memory allocation step.}
+
+\item{simplify}{Whether to simplify the profiles by removing
+intervening frames caused by lazy evaluation. This only has an
+effect on R 4.0. See the \code{filter.callframes} argument of
+\code{\link{Rprof}()}.}
 }
 \description{
 This function will run an R expression with profiling, and then return an