diff --git a/cli/tests/integration/npm_tests.rs b/cli/tests/integration/npm_tests.rs
index e29c1452e5..fb79a1cb0c 100644
--- a/cli/tests/integration/npm_tests.rs
+++ b/cli/tests/integration/npm_tests.rs
@@ -1470,6 +1470,14 @@ itest!(info_peer_deps_json {
   http_server: true,
 });
 
+itest!(create_require {
+  args: "run --reload npm/create_require/main.ts",
+  output: "npm/create_require/main.out",
+  exit_code: 0,
+  envs: env_vars(),
+  http_server: true,
+});
+
 fn env_vars_no_sync_download() -> Vec<(String, String)> {
   vec![
     ("DENO_NODE_COMPAT_URL".to_string(), util::std_file_url()),
diff --git a/cli/tests/testdata/npm/create_require/main.out b/cli/tests/testdata/npm/create_require/main.out
new file mode 100644
index 0000000000..ebd96c120a
--- /dev/null
+++ b/cli/tests/testdata/npm/create_require/main.out
@@ -0,0 +1,6 @@
+[WILDCARD]
+function
+function
+The argument 'filename' must be a file URL object, file URL string, or absolute path string. Received https://example.com/
+The argument 'filename' must be a file URL object, file URL string, or absolute path string. Received https://example.com/
+The argument 'filename' must be a file URL object, file URL string, or absolute path string. Received 1
diff --git a/cli/tests/testdata/npm/create_require/main.ts b/cli/tests/testdata/npm/create_require/main.ts
new file mode 100644
index 0000000000..625c734aaa
--- /dev/null
+++ b/cli/tests/testdata/npm/create_require/main.ts
@@ -0,0 +1 @@
+import "npm:@denotest/create-require@1.0.0";
diff --git a/cli/tests/testdata/npm/registry/@denotest/create-require/1.0.0/index.js b/cli/tests/testdata/npm/registry/@denotest/create-require/1.0.0/index.js
new file mode 100644
index 0000000000..eaa3e5afdf
--- /dev/null
+++ b/cli/tests/testdata/npm/registry/@denotest/create-require/1.0.0/index.js
@@ -0,0 +1,19 @@
+import { createRequire } from "module";
+
+console.log(typeof createRequire(import.meta.url));
+console.log(typeof createRequire(new URL(import.meta.url)));
+try {
+  createRequire("https://example.com/");
+} catch (e) {
+  console.log(e.message);
+}
+try {
+  createRequire(new URL("https://example.com/"));
+} catch (e) {
+  console.log(e.message);
+}
+try {
+  createRequire(1);
+} catch (e) {
+  console.log(e.message);
+}
diff --git a/cli/tests/testdata/npm/registry/@denotest/create-require/1.0.0/package.json b/cli/tests/testdata/npm/registry/@denotest/create-require/1.0.0/package.json
new file mode 100644
index 0000000000..00539643ec
--- /dev/null
+++ b/cli/tests/testdata/npm/registry/@denotest/create-require/1.0.0/package.json
@@ -0,0 +1,6 @@
+{
+  "name": "@denotest/create-require",
+  "version": "1.0.0",
+  "type": "module",
+  "main": "index.js"
+}
diff --git a/ext/node/02_require.js b/ext/node/02_require.js
index ac34a5fca7..372cc84719 100644
--- a/ext/node/02_require.js
+++ b/ext/node/02_require.js
@@ -819,8 +819,27 @@
   }
 
   function createRequire(filenameOrUrl) {
-    // FIXME: handle URLs and validation
-    const filename = core.ops.op_require_as_file_path(filenameOrUrl);
+    let fileUrlStr;
+    if (filenameOrUrl instanceof URL) {
+      if (filenameOrUrl.protocol !== "file:") {
+        throw new Error(
+          `The argument 'filename' must be a file URL object, file URL string, or absolute path string. Received ${filenameOrUrl}`,
+        );
+      }
+      fileUrlStr = filenameOrUrl.toString();
+    } else if (typeof filenameOrUrl === "string") {
+      if (!filenameOrUrl.startsWith("file:")) {
+        throw new Error(
+          `The argument 'filename' must be a file URL object, file URL string, or absolute path string. Received ${filenameOrUrl}`,
+        );
+      }
+      fileUrlStr = filenameOrUrl;
+    } else {
+      throw new Error(
+        `The argument 'filename' must be a file URL object, file URL string, or absolute path string. Received ${filenameOrUrl}`,
+      );
+    }
+    const filename = core.ops.op_require_as_file_path(fileUrlStr);
     return createRequireFromPath(filename);
   }