diff --git a/src/backend/commands/copyfrom.c b/src/backend/commands/copyfrom.c
index 40a54ad0bd..16d82d0140 100644
--- a/src/backend/commands/copyfrom.c
+++ b/src/backend/commands/copyfrom.c
@@ -53,6 +53,10 @@
 #include "utils/rel.h"
 #include "utils/snapmgr.h"
 
+#ifdef EMSCRIPTEN
+#include <emscripten.h>
+#endif
+
 /*
  * No more than this many tuples per CopyMultiInsertBuffer
  *
@@ -1169,6 +1173,20 @@ CopyFrom(CopyFromState cstate)
 	return processed;
 }
 
+/*
+ * Call the JS function that implements the COPY FROM to command.
+ */
+#ifdef EMSCRIPTEN
+EM_JS(char*, emscripten_copy_from, (char *filename, bool is_program), {
+	const res = Module.copyFrom(UTF8ToString(filename), is_program);
+	if (res === null || res === undefined) {
+		return null;
+	} else {
+		return stringToNewUTF8(res);
+	}
+});
+#endif
+
 /*
  * Setup to read tuples from a file for COPY FROM.
  *
@@ -1490,6 +1508,40 @@ BeginCopyFrom(ParseState *pstate,
 	{
 		cstate->filename = pstrdup(filename);
 
+		#ifdef EMSCRIPTEN
+		if (cstate->is_program)
+		{
+			/* JS implimentation of COPY FROM PROGRAM
+			 * Execute js runction Module.copyFrom, it run a function that implements
+			 * COPY FROM PROGRAM and make data availible at /dev/blob
+			 */
+			char* err_msg = emscripten_copy_from(cstate->filename, true);
+			if (err_msg != NULL)
+				ereport(ERROR,
+						(NULL,
+						 errmsg("could not execute command \"%s\": %s",
+								cstate->filename, err_msg)));
+			cstate->is_program = false;
+			cstate->filename = "/dev/blob";
+		}
+		else if (strncmp(cstate->filename, "http://", 7) == 0 ||
+				 strncmp(cstate->filename, "https://", 8) == 0 ||
+				 strncmp(cstate->filename, "blob:", 5) == 0)
+		{
+			/* JS implimentation of COPY FROM with a url path
+			 * a http prefix will do a synchronous GET request to the url
+			 * a blob prefix will fet the file from the query blobs option
+			 */
+			char* err_msg = emscripten_copy_from(cstate->filename, false);
+			if (err_msg != NULL)
+				ereport(ERROR,
+						(NULL,
+						 errmsg("could not COPY FROM \"%s\": %s",
+								cstate->filename, err_msg)));
+			cstate->filename = "/dev/blob";
+		}
+		#endif
+
 		if (cstate->is_program)
 		{
 			progress_vals[1] = PROGRESS_COPY_TYPE_PROGRAM;
diff --git a/src/backend/commands/copyto.c b/src/backend/commands/copyto.c
index b6eacd5baa..b737dba900 100644
--- a/src/backend/commands/copyto.c
+++ b/src/backend/commands/copyto.c
@@ -43,6 +43,10 @@
 #include "utils/rel.h"
 #include "utils/snapmgr.h"
 
+#ifdef EMSCRIPTEN
+#include <emscripten.h>
+#endif
+
 /*
  * Represents the different dest cases we need to worry about at
  * the bottom level
@@ -310,6 +314,20 @@ ClosePipeToProgram(CopyToState cstate)
 	}
 }
 
+/*
+ * Call the JS function that finalizes the COPY TO command.
+ */
+#ifdef EMSCRIPTEN
+EM_JS(char*, emscripten_copy_to_end, (), {
+	const res = Module.copyToEnd();
+	if (res === null || res === undefined) {
+		return null;
+	} else {
+		return stringToNewUTF8(res);
+	}
+});
+#endif
+
 /*
  * Release resources allocated in a cstate for COPY TO/FROM.
  */
@@ -329,12 +347,38 @@ EndCopy(CopyToState cstate)
 							cstate->filename)));
 	}
 
+	#ifdef EMSCRIPTEN
+	if (strcmp(cstate->filename, "/dev/blob") == 0)
+	{
+		/* Finalize the COPY TO command */
+		char* err_msg = emscripten_copy_to_end();
+		if (err_msg != NULL)
+			ereport(ERROR,
+					(NULL,
+					 errmsg("could not complete COPY TO: %s", err_msg)));
+	}
+	#endif
+
 	pgstat_progress_end_command();
 
 	MemoryContextDelete(cstate->copycontext);
 	pfree(cstate);
 }
 
+/*
+ * Call the JS function that implements the COPY TO command.
+ */
+#ifdef EMSCRIPTEN
+EM_JS(char*, emscripten_copy_to, (char *filename, bool is_program), {
+	const res = Module.copyTo(UTF8ToString(filename), is_program);
+	if (res === null || res === undefined) {
+		return null;
+	} else {
+		return stringToNewUTF8(res);
+	}
+});
+#endif
+
 /*
  * Setup CopyToState to read tuples from a table or a query for COPY TO.
  */
@@ -672,6 +716,40 @@ BeginCopyTo(ParseState *pstate,
 		cstate->filename = pstrdup(filename);
 		cstate->is_program = is_program;
 
+		#ifdef EMSCRIPTEN
+		if (cstate->is_program)
+		{
+			/* JS implimentation of COPY TO PROGRAM
+			 * Execute js runction Module.copyFrom, it run a function that implements
+			 * COPY FROM PROGRAM and make data availible at /dev/blob
+			 */
+			char* err_msg = emscripten_copy_to(cstate->filename, true);
+			if (err_msg != NULL)
+				ereport(ERROR,
+						(NULL,
+						 errmsg("could not execute command \"%s\": %s",
+								cstate->filename, err_msg)));
+			cstate->is_program = false;
+			cstate->filename = "/dev/blob";
+		}
+		else if (strncmp(cstate->filename, "http://", 7) == 0 ||
+				 strncmp(cstate->filename, "https://", 8) == 0 ||
+				 strncmp(cstate->filename, "blob:", 5) == 0)
+		{
+			/* JS implimentation of COPY FROM with a url path
+			 * a http prefix will do a synchronous GET request to the url
+			 * a blob prefix will fet the file from the query blobs option
+			 */
+			char* err_msg = emscripten_copy_to(cstate->filename, false);
+			if (err_msg != NULL)
+				ereport(ERROR,
+						(NULL,
+						 errmsg("could not COPY TO \"%s\": %s",
+								cstate->filename, err_msg)));
+			cstate->filename = "/dev/blob";
+		}
+		#endif
+
 		if (is_program)
 		{
 			progress_vals[1] = PROGRESS_COPY_TYPE_PROGRAM;
@@ -693,7 +771,7 @@ BeginCopyTo(ParseState *pstate,
 			 * Prevent write to relative path ... too easy to shoot oneself in
 			 * the foot by overwriting a database file ...
 			 */
-			if (!is_absolute_path(filename))
+			if (!is_absolute_path(cstate->filename))
 				ereport(ERROR,
 						(errcode(ERRCODE_INVALID_NAME),
 						 errmsg("relative path not allowed for COPY to file")));