I had a similar issue and ended up creating two neck and waist roots, one for the client and one for the server.
On the client that owns the character, clone both the neck and the waist, parent each motor6d to its respective body part, then disable (not destroy) the original motor (make sure to set Humanoid.RequiresNeck to false during this process, you can set it back to true when done).
Then every .1 seconds or so (I would advise against firing every frame, it may hog your request budget of 50kbps iirc and it will look fine if fired every .1 seconds), fire the server with the necessary data, then on the server set the C0 of the original neck and waist joints.
On a sidenote, I would recommend calculating C0 on the server as well, as an exploiter could spoof the CFrame that is sent and make their body parts weirdly positioned. That’s up to you though.
Here’s the thread if you want to read up: