diff --git a/java/src/org/openqa/selenium/interactions/Actions.java b/java/src/org/openqa/selenium/interactions/Actions.java
index bdec7bf3b94e3..ac6671e75d978 100644
--- a/java/src/org/openqa/selenium/interactions/Actions.java
+++ b/java/src/org/openqa/selenium/interactions/Actions.java
@@ -54,9 +54,15 @@ public class Actions {
   private PointerInput activePointer;
   private KeyInput activeKeyboard;
   private WheelInput activeWheel;
+  private Duration actionDuration;
 
   public Actions(WebDriver driver) {
+    this(driver, Duration.ofMillis(250));
+  }
+
+  public Actions(WebDriver driver, Duration duration) {
     this.driver = Require.nonNull("Driver", driver);
+    this.actionDuration = duration;
   }
 
   /**
@@ -215,7 +221,7 @@ public Actions release(WebElement target) {
    */
   public Actions scrollToElement(WebElement element) {
     WheelInput.ScrollOrigin scrollOrigin = WheelInput.ScrollOrigin.fromElement(element);
-    return tick(getActiveWheel().createScroll(0, 0, 0, 0, Duration.ofMillis(250), scrollOrigin));
+    return tick(getActiveWheel().createScroll(0, 0, 0, 0, this.actionDuration, scrollOrigin));
   }
 
   /**
@@ -229,7 +235,7 @@ public Actions scrollToElement(WebElement element) {
   public Actions scrollByAmount(int deltaX, int deltaY) {
     WheelInput.ScrollOrigin scrollOrigin = WheelInput.ScrollOrigin.fromViewport();
     return tick(
-        getActiveWheel().createScroll(0, 0, deltaX, deltaY, Duration.ofMillis(250), scrollOrigin));
+        getActiveWheel().createScroll(0, 0, deltaX, deltaY, this.actionDuration, scrollOrigin));
   }
 
   /**
@@ -249,7 +255,7 @@ public Actions scrollFromOrigin(WheelInput.ScrollOrigin scrollOrigin, int deltaX
     int x = scrollOrigin.getxOffset();
     int y = scrollOrigin.getyOffset();
     return tick(
-        getActiveWheel().createScroll(x, y, deltaX, deltaY, Duration.ofMillis(250), scrollOrigin));
+        getActiveWheel().createScroll(x, y, deltaX, deltaY, this.actionDuration, scrollOrigin));
   }
 
   /**
@@ -548,6 +554,10 @@ public WheelInput getActiveWheel() {
     return this.activeWheel;
   }
 
+  public Duration getActionDuration() {
+    return this.actionDuration;
+  }
+
   /**
    * Generates a composite action containing all actions so far, ready to be performed (and resets
    * the internal builder state, so subsequent calls to this method will contain fresh sequences).
diff --git a/java/test/org/openqa/selenium/interactions/ActionDurationTest.java b/java/test/org/openqa/selenium/interactions/ActionDurationTest.java
new file mode 100644
index 0000000000000..f9d603390eedf
--- /dev/null
+++ b/java/test/org/openqa/selenium/interactions/ActionDurationTest.java
@@ -0,0 +1,82 @@
+// Licensed to the Software Freedom Conservancy (SFC) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The SFC licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.openqa.selenium.interactions;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.time.Duration;
+import org.junit.jupiter.api.Tag;
+import org.junit.jupiter.api.Test;
+import org.openqa.selenium.By;
+import org.openqa.selenium.JavascriptExecutor;
+import org.openqa.selenium.WebElement;
+import org.openqa.selenium.testing.JupiterTestBase;
+
+@Tag("UnitTests")
+class ActionDurationTest extends JupiterTestBase {
+  @Test
+  void shouldScrollToElementWithCustomDuration() {
+    driver.get(
+        appServer.whereIs("scrolling_tests/frame_with_nested_scrolling_frame_out_of_view.html"));
+    WebElement iframe = driver.findElement(By.tagName("iframe"));
+
+    assertFalse(inViewport(iframe));
+
+    new Actions(driver, Duration.ofMillis(111)).scrollToElement(iframe).perform();
+
+    assertTrue(inViewport(iframe));
+  }
+
+  @Test
+  void shouldScrollFromViewportByGivenAmountWithCustomDuration() {
+    driver.get(
+        appServer.whereIs("scrolling_tests/frame_with_nested_scrolling_frame_out_of_view.html"));
+    WebElement footer = driver.findElement(By.tagName("footer"));
+    int deltaY = footer.getRect().y;
+
+    new Actions(driver, Duration.ofMillis(111)).scrollByAmount(0, deltaY).perform();
+
+    assertTrue(inViewport(footer));
+  }
+
+  @Test
+  void shouldBeDefaultActionDuration250ms() {
+    Actions actions = new Actions(driver);
+    assertEquals(Duration.ofMillis(250), actions.getActionDuration());
+  }
+
+  @Test
+  void shouldBeCustomDuration110ms() {
+    Actions actions = new Actions(driver, Duration.ofMillis(110));
+    assertEquals(Duration.ofMillis(110), actions.getActionDuration());
+  }
+
+  private boolean inViewport(WebElement element) {
+
+    String script =
+        "for(var e=arguments[0],f=e.offsetTop,t=e.offsetLeft,o=e.offsetWidth,n=e.offsetHeight;\n"
+            + "e.offsetParent;)f+=(e=e.offsetParent).offsetTop,t+=e.offsetLeft;\n"
+            + "return"
+            + " f<window.pageYOffset+window.innerHeight&&t<window.pageXOffset+window.innerWidth&&f+n>\n"
+            + "window.pageYOffset&&t+o>window.pageXOffset";
+
+    return (boolean) ((JavascriptExecutor) driver).executeScript(script, element);
+  }
+}